bpf, netns: Keep attached programs in bpf_prog_array
[linux-2.6-microblaze.git] / kernel / bpf / net_namespace.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/bpf.h>
4 #include <linux/filter.h>
5 #include <net/net_namespace.h>
6
7 /*
8  * Functions to manage BPF programs attached to netns
9  */
10
11 struct bpf_netns_link {
12         struct bpf_link link;
13         enum bpf_attach_type type;
14         enum netns_bpf_attach_type netns_type;
15
16         /* We don't hold a ref to net in order to auto-detach the link
17          * when netns is going away. Instead we rely on pernet
18          * pre_exit callback to clear this pointer. Must be accessed
19          * with netns_bpf_mutex held.
20          */
21         struct net *net;
22 };
23
24 /* Protects updates to netns_bpf */
25 DEFINE_MUTEX(netns_bpf_mutex);
26
27 /* Must be called with netns_bpf_mutex held. */
28 static void __net_exit bpf_netns_link_auto_detach(struct bpf_link *link)
29 {
30         struct bpf_netns_link *net_link =
31                 container_of(link, struct bpf_netns_link, link);
32
33         net_link->net = NULL;
34 }
35
36 /* Must be called with netns_bpf_mutex held. */
37 static void netns_bpf_run_array_detach(struct net *net,
38                                        enum netns_bpf_attach_type type)
39 {
40         struct bpf_prog_array *run_array;
41
42         run_array = rcu_replace_pointer(net->bpf.run_array[type], NULL,
43                                         lockdep_is_held(&netns_bpf_mutex));
44         bpf_prog_array_free(run_array);
45 }
46
47 static void bpf_netns_link_release(struct bpf_link *link)
48 {
49         struct bpf_netns_link *net_link =
50                 container_of(link, struct bpf_netns_link, link);
51         enum netns_bpf_attach_type type = net_link->netns_type;
52         struct net *net;
53
54         /* Link auto-detached by dying netns. */
55         if (!net_link->net)
56                 return;
57
58         mutex_lock(&netns_bpf_mutex);
59
60         /* Recheck after potential sleep. We can race with cleanup_net
61          * here, but if we see a non-NULL struct net pointer pre_exit
62          * has not happened yet and will block on netns_bpf_mutex.
63          */
64         net = net_link->net;
65         if (!net)
66                 goto out_unlock;
67
68         netns_bpf_run_array_detach(net, type);
69         net->bpf.links[type] = NULL;
70
71 out_unlock:
72         mutex_unlock(&netns_bpf_mutex);
73 }
74
75 static void bpf_netns_link_dealloc(struct bpf_link *link)
76 {
77         struct bpf_netns_link *net_link =
78                 container_of(link, struct bpf_netns_link, link);
79
80         kfree(net_link);
81 }
82
83 static int bpf_netns_link_update_prog(struct bpf_link *link,
84                                       struct bpf_prog *new_prog,
85                                       struct bpf_prog *old_prog)
86 {
87         struct bpf_netns_link *net_link =
88                 container_of(link, struct bpf_netns_link, link);
89         enum netns_bpf_attach_type type = net_link->netns_type;
90         struct bpf_prog_array *run_array;
91         struct net *net;
92         int ret = 0;
93
94         if (old_prog && old_prog != link->prog)
95                 return -EPERM;
96         if (new_prog->type != link->prog->type)
97                 return -EINVAL;
98
99         mutex_lock(&netns_bpf_mutex);
100
101         net = net_link->net;
102         if (!net || !check_net(net)) {
103                 /* Link auto-detached or netns dying */
104                 ret = -ENOLINK;
105                 goto out_unlock;
106         }
107
108         run_array = rcu_dereference_protected(net->bpf.run_array[type],
109                                               lockdep_is_held(&netns_bpf_mutex));
110         WRITE_ONCE(run_array->items[0].prog, new_prog);
111
112         old_prog = xchg(&link->prog, new_prog);
113         bpf_prog_put(old_prog);
114
115 out_unlock:
116         mutex_unlock(&netns_bpf_mutex);
117         return ret;
118 }
119
120 static int bpf_netns_link_fill_info(const struct bpf_link *link,
121                                     struct bpf_link_info *info)
122 {
123         const struct bpf_netns_link *net_link =
124                 container_of(link, struct bpf_netns_link, link);
125         unsigned int inum = 0;
126         struct net *net;
127
128         mutex_lock(&netns_bpf_mutex);
129         net = net_link->net;
130         if (net && check_net(net))
131                 inum = net->ns.inum;
132         mutex_unlock(&netns_bpf_mutex);
133
134         info->netns.netns_ino = inum;
135         info->netns.attach_type = net_link->type;
136         return 0;
137 }
138
139 static void bpf_netns_link_show_fdinfo(const struct bpf_link *link,
140                                        struct seq_file *seq)
141 {
142         struct bpf_link_info info = {};
143
144         bpf_netns_link_fill_info(link, &info);
145         seq_printf(seq,
146                    "netns_ino:\t%u\n"
147                    "attach_type:\t%u\n",
148                    info.netns.netns_ino,
149                    info.netns.attach_type);
150 }
151
152 static const struct bpf_link_ops bpf_netns_link_ops = {
153         .release = bpf_netns_link_release,
154         .dealloc = bpf_netns_link_dealloc,
155         .update_prog = bpf_netns_link_update_prog,
156         .fill_link_info = bpf_netns_link_fill_info,
157         .show_fdinfo = bpf_netns_link_show_fdinfo,
158 };
159
160 /* Must be called with netns_bpf_mutex held. */
161 static int __netns_bpf_prog_query(const union bpf_attr *attr,
162                                   union bpf_attr __user *uattr,
163                                   struct net *net,
164                                   enum netns_bpf_attach_type type)
165 {
166         __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
167         struct bpf_prog_array *run_array;
168         u32 prog_cnt = 0, flags = 0;
169
170         run_array = rcu_dereference_protected(net->bpf.run_array[type],
171                                               lockdep_is_held(&netns_bpf_mutex));
172         if (run_array)
173                 prog_cnt = bpf_prog_array_length(run_array);
174
175         if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
176                 return -EFAULT;
177         if (copy_to_user(&uattr->query.prog_cnt, &prog_cnt, sizeof(prog_cnt)))
178                 return -EFAULT;
179         if (!attr->query.prog_cnt || !prog_ids || !prog_cnt)
180                 return 0;
181
182         return bpf_prog_array_copy_to_user(run_array, prog_ids,
183                                            attr->query.prog_cnt);
184 }
185
186 int netns_bpf_prog_query(const union bpf_attr *attr,
187                          union bpf_attr __user *uattr)
188 {
189         enum netns_bpf_attach_type type;
190         struct net *net;
191         int ret;
192
193         if (attr->query.query_flags)
194                 return -EINVAL;
195
196         type = to_netns_bpf_attach_type(attr->query.attach_type);
197         if (type < 0)
198                 return -EINVAL;
199
200         net = get_net_ns_by_fd(attr->query.target_fd);
201         if (IS_ERR(net))
202                 return PTR_ERR(net);
203
204         mutex_lock(&netns_bpf_mutex);
205         ret = __netns_bpf_prog_query(attr, uattr, net, type);
206         mutex_unlock(&netns_bpf_mutex);
207
208         put_net(net);
209         return ret;
210 }
211
212 int netns_bpf_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
213 {
214         struct bpf_prog_array *run_array;
215         enum netns_bpf_attach_type type;
216         struct bpf_prog *attached;
217         struct net *net;
218         int ret;
219
220         type = to_netns_bpf_attach_type(attr->attach_type);
221         if (type < 0)
222                 return -EINVAL;
223
224         net = current->nsproxy->net_ns;
225         mutex_lock(&netns_bpf_mutex);
226
227         /* Attaching prog directly is not compatible with links */
228         if (net->bpf.links[type]) {
229                 ret = -EEXIST;
230                 goto out_unlock;
231         }
232
233         switch (type) {
234         case NETNS_BPF_FLOW_DISSECTOR:
235                 ret = flow_dissector_bpf_prog_attach_check(net, prog);
236                 break;
237         default:
238                 ret = -EINVAL;
239                 break;
240         }
241         if (ret)
242                 goto out_unlock;
243
244         attached = net->bpf.progs[type];
245         if (attached == prog) {
246                 /* The same program cannot be attached twice */
247                 ret = -EINVAL;
248                 goto out_unlock;
249         }
250
251         run_array = rcu_dereference_protected(net->bpf.run_array[type],
252                                               lockdep_is_held(&netns_bpf_mutex));
253         if (run_array) {
254                 WRITE_ONCE(run_array->items[0].prog, prog);
255         } else {
256                 run_array = bpf_prog_array_alloc(1, GFP_KERNEL);
257                 if (!run_array) {
258                         ret = -ENOMEM;
259                         goto out_unlock;
260                 }
261                 run_array->items[0].prog = prog;
262                 rcu_assign_pointer(net->bpf.run_array[type], run_array);
263         }
264
265         net->bpf.progs[type] = prog;
266         if (attached)
267                 bpf_prog_put(attached);
268
269 out_unlock:
270         mutex_unlock(&netns_bpf_mutex);
271
272         return ret;
273 }
274
275 /* Must be called with netns_bpf_mutex held. */
276 static int __netns_bpf_prog_detach(struct net *net,
277                                    enum netns_bpf_attach_type type)
278 {
279         struct bpf_prog *attached;
280
281         /* Progs attached via links cannot be detached */
282         if (net->bpf.links[type])
283                 return -EINVAL;
284
285         attached = net->bpf.progs[type];
286         if (!attached)
287                 return -ENOENT;
288         netns_bpf_run_array_detach(net, type);
289         net->bpf.progs[type] = NULL;
290         bpf_prog_put(attached);
291         return 0;
292 }
293
294 int netns_bpf_prog_detach(const union bpf_attr *attr)
295 {
296         enum netns_bpf_attach_type type;
297         int ret;
298
299         type = to_netns_bpf_attach_type(attr->attach_type);
300         if (type < 0)
301                 return -EINVAL;
302
303         mutex_lock(&netns_bpf_mutex);
304         ret = __netns_bpf_prog_detach(current->nsproxy->net_ns, type);
305         mutex_unlock(&netns_bpf_mutex);
306
307         return ret;
308 }
309
310 static int netns_bpf_link_attach(struct net *net, struct bpf_link *link,
311                                  enum netns_bpf_attach_type type)
312 {
313         struct bpf_prog_array *run_array;
314         int err;
315
316         mutex_lock(&netns_bpf_mutex);
317
318         /* Allow attaching only one prog or link for now */
319         if (net->bpf.links[type]) {
320                 err = -E2BIG;
321                 goto out_unlock;
322         }
323         /* Links are not compatible with attaching prog directly */
324         if (net->bpf.progs[type]) {
325                 err = -EEXIST;
326                 goto out_unlock;
327         }
328
329         switch (type) {
330         case NETNS_BPF_FLOW_DISSECTOR:
331                 err = flow_dissector_bpf_prog_attach_check(net, link->prog);
332                 break;
333         default:
334                 err = -EINVAL;
335                 break;
336         }
337         if (err)
338                 goto out_unlock;
339
340         run_array = bpf_prog_array_alloc(1, GFP_KERNEL);
341         if (!run_array) {
342                 err = -ENOMEM;
343                 goto out_unlock;
344         }
345         run_array->items[0].prog = link->prog;
346         rcu_assign_pointer(net->bpf.run_array[type], run_array);
347
348         net->bpf.links[type] = link;
349
350 out_unlock:
351         mutex_unlock(&netns_bpf_mutex);
352         return err;
353 }
354
355 int netns_bpf_link_create(const union bpf_attr *attr, struct bpf_prog *prog)
356 {
357         enum netns_bpf_attach_type netns_type;
358         struct bpf_link_primer link_primer;
359         struct bpf_netns_link *net_link;
360         enum bpf_attach_type type;
361         struct net *net;
362         int err;
363
364         if (attr->link_create.flags)
365                 return -EINVAL;
366
367         type = attr->link_create.attach_type;
368         netns_type = to_netns_bpf_attach_type(type);
369         if (netns_type < 0)
370                 return -EINVAL;
371
372         net = get_net_ns_by_fd(attr->link_create.target_fd);
373         if (IS_ERR(net))
374                 return PTR_ERR(net);
375
376         net_link = kzalloc(sizeof(*net_link), GFP_USER);
377         if (!net_link) {
378                 err = -ENOMEM;
379                 goto out_put_net;
380         }
381         bpf_link_init(&net_link->link, BPF_LINK_TYPE_NETNS,
382                       &bpf_netns_link_ops, prog);
383         net_link->net = net;
384         net_link->type = type;
385         net_link->netns_type = netns_type;
386
387         err = bpf_link_prime(&net_link->link, &link_primer);
388         if (err) {
389                 kfree(net_link);
390                 goto out_put_net;
391         }
392
393         err = netns_bpf_link_attach(net, &net_link->link, netns_type);
394         if (err) {
395                 bpf_link_cleanup(&link_primer);
396                 goto out_put_net;
397         }
398
399         put_net(net);
400         return bpf_link_settle(&link_primer);
401
402 out_put_net:
403         put_net(net);
404         return err;
405 }
406
407 static void __net_exit netns_bpf_pernet_pre_exit(struct net *net)
408 {
409         enum netns_bpf_attach_type type;
410         struct bpf_link *link;
411
412         mutex_lock(&netns_bpf_mutex);
413         for (type = 0; type < MAX_NETNS_BPF_ATTACH_TYPE; type++) {
414                 netns_bpf_run_array_detach(net, type);
415                 link = net->bpf.links[type];
416                 if (link)
417                         bpf_netns_link_auto_detach(link);
418                 else if (net->bpf.progs[type])
419                         bpf_prog_put(net->bpf.progs[type]);
420         }
421         mutex_unlock(&netns_bpf_mutex);
422 }
423
424 static struct pernet_operations netns_bpf_pernet_ops __net_initdata = {
425         .pre_exit = netns_bpf_pernet_pre_exit,
426 };
427
428 static int __init netns_bpf_init(void)
429 {
430         return register_pernet_subsys(&netns_bpf_pernet_ops);
431 }
432
433 subsys_initcall(netns_bpf_init);