diff options
-rw-r--r-- | kernel/bpf/offload.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/kernel/bpf/offload.c b/kernel/bpf/offload.c index 001ddfde7874..cdd1e19a668b 100644 --- a/kernel/bpf/offload.c +++ b/kernel/bpf/offload.c | |||
@@ -30,9 +30,19 @@ | |||
30 | static DECLARE_RWSEM(bpf_devs_lock); | 30 | static DECLARE_RWSEM(bpf_devs_lock); |
31 | static LIST_HEAD(bpf_prog_offload_devs); | 31 | static LIST_HEAD(bpf_prog_offload_devs); |
32 | 32 | ||
33 | static int bpf_dev_offload_check(struct net_device *netdev) | ||
34 | { | ||
35 | if (!netdev) | ||
36 | return -EINVAL; | ||
37 | if (!netdev->netdev_ops->ndo_bpf) | ||
38 | return -EOPNOTSUPP; | ||
39 | return 0; | ||
40 | } | ||
41 | |||
33 | int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr) | 42 | int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr) |
34 | { | 43 | { |
35 | struct bpf_prog_offload *offload; | 44 | struct bpf_prog_offload *offload; |
45 | int err; | ||
36 | 46 | ||
37 | if (attr->prog_type != BPF_PROG_TYPE_SCHED_CLS && | 47 | if (attr->prog_type != BPF_PROG_TYPE_SCHED_CLS && |
38 | attr->prog_type != BPF_PROG_TYPE_XDP) | 48 | attr->prog_type != BPF_PROG_TYPE_XDP) |
@@ -49,12 +59,15 @@ int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr) | |||
49 | 59 | ||
50 | offload->netdev = dev_get_by_index(current->nsproxy->net_ns, | 60 | offload->netdev = dev_get_by_index(current->nsproxy->net_ns, |
51 | attr->prog_ifindex); | 61 | attr->prog_ifindex); |
52 | if (!offload->netdev) | 62 | err = bpf_dev_offload_check(offload->netdev); |
53 | goto err_free; | 63 | if (err) |
64 | goto err_maybe_put; | ||
54 | 65 | ||
55 | down_write(&bpf_devs_lock); | 66 | down_write(&bpf_devs_lock); |
56 | if (offload->netdev->reg_state != NETREG_REGISTERED) | 67 | if (offload->netdev->reg_state != NETREG_REGISTERED) { |
68 | err = -EINVAL; | ||
57 | goto err_unlock; | 69 | goto err_unlock; |
70 | } | ||
58 | prog->aux->offload = offload; | 71 | prog->aux->offload = offload; |
59 | list_add_tail(&offload->offloads, &bpf_prog_offload_devs); | 72 | list_add_tail(&offload->offloads, &bpf_prog_offload_devs); |
60 | dev_put(offload->netdev); | 73 | dev_put(offload->netdev); |
@@ -63,10 +76,11 @@ int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr) | |||
63 | return 0; | 76 | return 0; |
64 | err_unlock: | 77 | err_unlock: |
65 | up_write(&bpf_devs_lock); | 78 | up_write(&bpf_devs_lock); |
66 | dev_put(offload->netdev); | 79 | err_maybe_put: |
67 | err_free: | 80 | if (offload->netdev) |
81 | dev_put(offload->netdev); | ||
68 | kfree(offload); | 82 | kfree(offload); |
69 | return -EINVAL; | 83 | return err; |
70 | } | 84 | } |
71 | 85 | ||
72 | static int __bpf_offload_ndo(struct bpf_prog *prog, enum bpf_netdev_command cmd, | 86 | static int __bpf_offload_ndo(struct bpf_prog *prog, enum bpf_netdev_command cmd, |
@@ -80,8 +94,6 @@ static int __bpf_offload_ndo(struct bpf_prog *prog, enum bpf_netdev_command cmd, | |||
80 | if (!offload) | 94 | if (!offload) |
81 | return -ENODEV; | 95 | return -ENODEV; |
82 | netdev = offload->netdev; | 96 | netdev = offload->netdev; |
83 | if (!netdev->netdev_ops->ndo_bpf) | ||
84 | return -EOPNOTSUPP; | ||
85 | 97 | ||
86 | data->command = cmd; | 98 | data->command = cmd; |
87 | 99 | ||