]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - kernel/bpf/offload.c
mmc: core: prepend 0x to OCR entry in sysfs
[mirror_ubuntu-bionic-kernel.git] / kernel / bpf / offload.c
1 #include <linux/bpf.h>
2 #include <linux/bpf_verifier.h>
3 #include <linux/bug.h>
4 #include <linux/list.h>
5 #include <linux/netdevice.h>
6 #include <linux/printk.h>
7 #include <linux/rtnetlink.h>
8
9 /* protected by RTNL */
10 static LIST_HEAD(bpf_prog_offload_devs);
11
12 int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr)
13 {
14 struct net *net = current->nsproxy->net_ns;
15 struct bpf_dev_offload *offload;
16
17 if (!capable(CAP_SYS_ADMIN))
18 return -EPERM;
19
20 if (attr->prog_flags)
21 return -EINVAL;
22
23 offload = kzalloc(sizeof(*offload), GFP_USER);
24 if (!offload)
25 return -ENOMEM;
26
27 offload->prog = prog;
28 init_waitqueue_head(&offload->verifier_done);
29
30 rtnl_lock();
31 offload->netdev = __dev_get_by_index(net, attr->prog_target_ifindex);
32 if (!offload->netdev) {
33 rtnl_unlock();
34 kfree(offload);
35 return -EINVAL;
36 }
37
38 prog->aux->offload = offload;
39 list_add_tail(&offload->offloads, &bpf_prog_offload_devs);
40 rtnl_unlock();
41
42 return 0;
43 }
44
45 static int __bpf_offload_ndo(struct bpf_prog *prog, enum bpf_netdev_command cmd,
46 struct netdev_bpf *data)
47 {
48 struct net_device *netdev = prog->aux->offload->netdev;
49
50 ASSERT_RTNL();
51
52 if (!netdev)
53 return -ENODEV;
54 if (!netdev->netdev_ops->ndo_bpf)
55 return -EOPNOTSUPP;
56
57 data->command = cmd;
58
59 return netdev->netdev_ops->ndo_bpf(netdev, data);
60 }
61
62 int bpf_prog_offload_verifier_prep(struct bpf_verifier_env *env)
63 {
64 struct netdev_bpf data = {};
65 int err;
66
67 data.verifier.prog = env->prog;
68
69 rtnl_lock();
70 err = __bpf_offload_ndo(env->prog, BPF_OFFLOAD_VERIFIER_PREP, &data);
71 if (err)
72 goto exit_unlock;
73
74 env->dev_ops = data.verifier.ops;
75
76 env->prog->aux->offload->dev_state = true;
77 env->prog->aux->offload->verifier_running = true;
78 exit_unlock:
79 rtnl_unlock();
80 return err;
81 }
82
83 static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
84 {
85 struct bpf_dev_offload *offload = prog->aux->offload;
86 struct netdev_bpf data = {};
87
88 data.offload.prog = prog;
89
90 if (offload->verifier_running)
91 wait_event(offload->verifier_done, !offload->verifier_running);
92
93 if (offload->dev_state)
94 WARN_ON(__bpf_offload_ndo(prog, BPF_OFFLOAD_DESTROY, &data));
95
96 offload->dev_state = false;
97 list_del_init(&offload->offloads);
98 offload->netdev = NULL;
99 }
100
101 void bpf_prog_offload_destroy(struct bpf_prog *prog)
102 {
103 struct bpf_dev_offload *offload = prog->aux->offload;
104
105 offload->verifier_running = false;
106 wake_up(&offload->verifier_done);
107
108 rtnl_lock();
109 __bpf_prog_offload_destroy(prog);
110 rtnl_unlock();
111
112 kfree(offload);
113 }
114
115 static int bpf_prog_offload_translate(struct bpf_prog *prog)
116 {
117 struct bpf_dev_offload *offload = prog->aux->offload;
118 struct netdev_bpf data = {};
119 int ret;
120
121 data.offload.prog = prog;
122
123 offload->verifier_running = false;
124 wake_up(&offload->verifier_done);
125
126 rtnl_lock();
127 ret = __bpf_offload_ndo(prog, BPF_OFFLOAD_TRANSLATE, &data);
128 rtnl_unlock();
129
130 return ret;
131 }
132
133 static unsigned int bpf_prog_warn_on_exec(const void *ctx,
134 const struct bpf_insn *insn)
135 {
136 WARN(1, "attempt to execute device eBPF program on the host!");
137 return 0;
138 }
139
140 int bpf_prog_offload_compile(struct bpf_prog *prog)
141 {
142 prog->bpf_func = bpf_prog_warn_on_exec;
143
144 return bpf_prog_offload_translate(prog);
145 }
146
147 u32 bpf_prog_offload_ifindex(struct bpf_prog *prog)
148 {
149 struct bpf_dev_offload *offload = prog->aux->offload;
150 u32 ifindex;
151
152 rtnl_lock();
153 ifindex = offload->netdev ? offload->netdev->ifindex : 0;
154 rtnl_unlock();
155
156 return ifindex;
157 }
158
159 const struct bpf_prog_ops bpf_offload_prog_ops = {
160 };
161
162 static int bpf_offload_notification(struct notifier_block *notifier,
163 ulong event, void *ptr)
164 {
165 struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
166 struct bpf_dev_offload *offload, *tmp;
167
168 ASSERT_RTNL();
169
170 switch (event) {
171 case NETDEV_UNREGISTER:
172 list_for_each_entry_safe(offload, tmp, &bpf_prog_offload_devs,
173 offloads) {
174 if (offload->netdev == netdev)
175 __bpf_prog_offload_destroy(offload->prog);
176 }
177 break;
178 default:
179 break;
180 }
181 return NOTIFY_OK;
182 }
183
184 static struct notifier_block bpf_offload_notifier = {
185 .notifier_call = bpf_offload_notification,
186 };
187
188 static int __init bpf_offload_init(void)
189 {
190 register_netdevice_notifier(&bpf_offload_notifier);
191 return 0;
192 }
193
194 subsys_initcall(bpf_offload_init);