Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+9 −14
Original line number Diff line number Diff line
@@ -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,
			     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();

	if (!netdev)
	if (!offload)
		return -ENODEV;
	netdev = offload->netdev;
	if (!netdev->netdev_ops->ndo_bpf)
		return -EOPNOTSUPP;

@@ -111,7 +113,7 @@ int bpf_prog_offload_verify_insn(struct bpf_verifier_env *env,

	down_read(&bpf_devs_lock);
	offload = env->prog->aux->offload;
	if (offload->netdev)
	if (offload)
		ret = offload->dev_ops->insn_hook(env, insn_idx, prev_insn_idx);
	up_read(&bpf_devs_lock);

@@ -123,31 +125,24 @@ static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
	struct bpf_dev_offload *offload = prog->aux->offload;
	struct netdev_bpf data = {};

	/* Caution - if netdev is destroyed before the program, this function
	 * will be called twice.
	 */

	data.offload.prog = prog;

	if (offload->dev_state)
		WARN_ON(__bpf_offload_ndo(prog, BPF_OFFLOAD_DESTROY, &data));

	offload->dev_state = false;
	list_del_init(&offload->offloads);
	offload->netdev = NULL;
	kfree(offload);
	prog->aux->offload = NULL;
}

void bpf_prog_offload_destroy(struct bpf_prog *prog)
{
	struct bpf_dev_offload *offload = prog->aux->offload;

	rtnl_lock();
	down_write(&bpf_devs_lock);
	if (prog->aux->offload)
		__bpf_prog_offload_destroy(prog);
	up_write(&bpf_devs_lock);
	rtnl_unlock();

	kfree(offload);
}

static int bpf_prog_offload_translate(struct bpf_prog *prog)