diff options
Diffstat (limited to 'kernel/bpf')
| -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 | ||
