Commit ce3b9db4 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Daniel Borkmann

bpf: offload: free prog->aux->offload when device disappears

All bpf offload operations should now be under bpf_devs_lock,
it's safe to free and clear the entire offload structure,
not only the netdev pointer.

__bpf_prog_offload_destroy() will no longer be called multiple
times.
Suggested-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarQuentin Monnet <quentin.monnet@netronome.com>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent cae1927c
...@@ -70,12 +70,14 @@ int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr) ...@@ -70,12 +70,14 @@ int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr)
static int __bpf_offload_ndo(struct bpf_prog *prog, enum bpf_netdev_command cmd, static int __bpf_offload_ndo(struct bpf_prog *prog, enum bpf_netdev_command cmd,
struct netdev_bpf *data) struct netdev_bpf *data)
{ {
struct net_device *netdev = prog->aux->offload->netdev; struct bpf_dev_offload *offload = prog->aux->offload;
struct net_device *netdev;
ASSERT_RTNL(); ASSERT_RTNL();
if (!netdev) if (!offload)
return -ENODEV; return -ENODEV;
netdev = offload->netdev;
if (!netdev->netdev_ops->ndo_bpf) if (!netdev->netdev_ops->ndo_bpf)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -111,7 +113,7 @@ int bpf_prog_offload_verify_insn(struct bpf_verifier_env *env, ...@@ -111,7 +113,7 @@ int bpf_prog_offload_verify_insn(struct bpf_verifier_env *env,
down_read(&bpf_devs_lock); down_read(&bpf_devs_lock);
offload = env->prog->aux->offload; offload = env->prog->aux->offload;
if (offload->netdev) if (offload)
ret = offload->dev_ops->insn_hook(env, insn_idx, prev_insn_idx); ret = offload->dev_ops->insn_hook(env, insn_idx, prev_insn_idx);
up_read(&bpf_devs_lock); up_read(&bpf_devs_lock);
...@@ -123,31 +125,24 @@ static void __bpf_prog_offload_destroy(struct bpf_prog *prog) ...@@ -123,31 +125,24 @@ static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
struct bpf_dev_offload *offload = prog->aux->offload; struct bpf_dev_offload *offload = prog->aux->offload;
struct netdev_bpf data = {}; struct netdev_bpf data = {};
/* Caution - if netdev is destroyed before the program, this function
* will be called twice.
*/
data.offload.prog = prog; data.offload.prog = prog;
if (offload->dev_state) if (offload->dev_state)
WARN_ON(__bpf_offload_ndo(prog, BPF_OFFLOAD_DESTROY, &data)); WARN_ON(__bpf_offload_ndo(prog, BPF_OFFLOAD_DESTROY, &data));
offload->dev_state = false;
list_del_init(&offload->offloads); list_del_init(&offload->offloads);
offload->netdev = NULL; kfree(offload);
prog->aux->offload = NULL;
} }
void bpf_prog_offload_destroy(struct bpf_prog *prog) void bpf_prog_offload_destroy(struct bpf_prog *prog)
{ {
struct bpf_dev_offload *offload = prog->aux->offload;
rtnl_lock(); rtnl_lock();
down_write(&bpf_devs_lock); down_write(&bpf_devs_lock);
__bpf_prog_offload_destroy(prog); if (prog->aux->offload)
__bpf_prog_offload_destroy(prog);
up_write(&bpf_devs_lock); up_write(&bpf_devs_lock);
rtnl_unlock(); rtnl_unlock();
kfree(offload);
} }
static int bpf_prog_offload_translate(struct bpf_prog *prog) static int bpf_prog_offload_translate(struct bpf_prog *prog)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment