Linux-libre 4.17.3-gnu
[librecmc/linux-libre.git] / tools / lib / bpf / bpf.c
1 // SPDX-License-Identifier: LGPL-2.1
2
3 /*
4  * common eBPF ELF operations.
5  *
6  * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
7  * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
8  * Copyright (C) 2015 Huawei Inc.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation;
13  * version 2.1 of the License (not later!)
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this program; if not,  see <http://www.gnu.org/licenses>
22  */
23
24 #include <stdlib.h>
25 #include <memory.h>
26 #include <unistd.h>
27 #include <asm/unistd.h>
28 #include <linux/bpf.h>
29 #include "bpf.h"
30 #include "libbpf.h"
31 #include "nlattr.h"
32 #include <linux/rtnetlink.h>
33 #include <linux/if_link.h>
34 #include <sys/socket.h>
35 #include <errno.h>
36
37 #ifndef SOL_NETLINK
38 #define SOL_NETLINK 270
39 #endif
40
41 /*
42  * When building perf, unistd.h is overridden. __NR_bpf is
43  * required to be defined explicitly.
44  */
45 #ifndef __NR_bpf
46 # if defined(__i386__)
47 #  define __NR_bpf 357
48 # elif defined(__x86_64__)
49 #  define __NR_bpf 321
50 # elif defined(__aarch64__)
51 #  define __NR_bpf 280
52 # elif defined(__sparc__)
53 #  define __NR_bpf 349
54 # elif defined(__s390__)
55 #  define __NR_bpf 351
56 # else
57 #  error __NR_bpf not defined. libbpf does not support your arch.
58 # endif
59 #endif
60
61 #ifndef min
62 #define min(x, y) ((x) < (y) ? (x) : (y))
63 #endif
64
65 static inline __u64 ptr_to_u64(const void *ptr)
66 {
67         return (__u64) (unsigned long) ptr;
68 }
69
70 static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
71                           unsigned int size)
72 {
73         return syscall(__NR_bpf, cmd, attr, size);
74 }
75
76 int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
77                         int key_size, int value_size, int max_entries,
78                         __u32 map_flags, int node)
79 {
80         __u32 name_len = name ? strlen(name) : 0;
81         union bpf_attr attr;
82
83         memset(&attr, '\0', sizeof(attr));
84
85         attr.map_type = map_type;
86         attr.key_size = key_size;
87         attr.value_size = value_size;
88         attr.max_entries = max_entries;
89         attr.map_flags = map_flags;
90         memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
91
92         if (node >= 0) {
93                 attr.map_flags |= BPF_F_NUMA_NODE;
94                 attr.numa_node = node;
95         }
96
97         return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
98 }
99
100 int bpf_create_map(enum bpf_map_type map_type, int key_size,
101                    int value_size, int max_entries, __u32 map_flags)
102 {
103         return bpf_create_map_node(map_type, NULL, key_size, value_size,
104                                    max_entries, map_flags, -1);
105 }
106
107 int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
108                         int key_size, int value_size, int max_entries,
109                         __u32 map_flags)
110 {
111         return bpf_create_map_node(map_type, name, key_size, value_size,
112                                    max_entries, map_flags, -1);
113 }
114
115 int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
116                                int key_size, int inner_map_fd, int max_entries,
117                                __u32 map_flags, int node)
118 {
119         __u32 name_len = name ? strlen(name) : 0;
120         union bpf_attr attr;
121
122         memset(&attr, '\0', sizeof(attr));
123
124         attr.map_type = map_type;
125         attr.key_size = key_size;
126         attr.value_size = 4;
127         attr.inner_map_fd = inner_map_fd;
128         attr.max_entries = max_entries;
129         attr.map_flags = map_flags;
130         memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
131
132         if (node >= 0) {
133                 attr.map_flags |= BPF_F_NUMA_NODE;
134                 attr.numa_node = node;
135         }
136
137         return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
138 }
139
140 int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
141                           int key_size, int inner_map_fd, int max_entries,
142                           __u32 map_flags)
143 {
144         return bpf_create_map_in_map_node(map_type, name, key_size,
145                                           inner_map_fd, max_entries, map_flags,
146                                           -1);
147 }
148
149 int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
150                            char *log_buf, size_t log_buf_sz)
151 {
152         union bpf_attr attr;
153         __u32 name_len;
154         int fd;
155
156         if (!load_attr)
157                 return -EINVAL;
158
159         name_len = load_attr->name ? strlen(load_attr->name) : 0;
160
161         bzero(&attr, sizeof(attr));
162         attr.prog_type = load_attr->prog_type;
163         attr.expected_attach_type = load_attr->expected_attach_type;
164         attr.insn_cnt = (__u32)load_attr->insns_cnt;
165         attr.insns = ptr_to_u64(load_attr->insns);
166         attr.license = ptr_to_u64(load_attr->license);
167         attr.log_buf = ptr_to_u64(NULL);
168         attr.log_size = 0;
169         attr.log_level = 0;
170         attr.kern_version = load_attr->kern_version;
171         memcpy(attr.prog_name, load_attr->name,
172                min(name_len, BPF_OBJ_NAME_LEN - 1));
173
174         fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
175         if (fd >= 0 || !log_buf || !log_buf_sz)
176                 return fd;
177
178         /* Try again with log */
179         attr.log_buf = ptr_to_u64(log_buf);
180         attr.log_size = log_buf_sz;
181         attr.log_level = 1;
182         log_buf[0] = 0;
183         return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
184 }
185
186 int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
187                      size_t insns_cnt, const char *license,
188                      __u32 kern_version, char *log_buf,
189                      size_t log_buf_sz)
190 {
191         struct bpf_load_program_attr load_attr;
192
193         memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
194         load_attr.prog_type = type;
195         load_attr.expected_attach_type = 0;
196         load_attr.name = NULL;
197         load_attr.insns = insns;
198         load_attr.insns_cnt = insns_cnt;
199         load_attr.license = license;
200         load_attr.kern_version = kern_version;
201
202         return bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz);
203 }
204
205 int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
206                        size_t insns_cnt, int strict_alignment,
207                        const char *license, __u32 kern_version,
208                        char *log_buf, size_t log_buf_sz, int log_level)
209 {
210         union bpf_attr attr;
211
212         bzero(&attr, sizeof(attr));
213         attr.prog_type = type;
214         attr.insn_cnt = (__u32)insns_cnt;
215         attr.insns = ptr_to_u64(insns);
216         attr.license = ptr_to_u64(license);
217         attr.log_buf = ptr_to_u64(log_buf);
218         attr.log_size = log_buf_sz;
219         attr.log_level = log_level;
220         log_buf[0] = 0;
221         attr.kern_version = kern_version;
222         attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0;
223
224         return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
225 }
226
227 int bpf_map_update_elem(int fd, const void *key, const void *value,
228                         __u64 flags)
229 {
230         union bpf_attr attr;
231
232         bzero(&attr, sizeof(attr));
233         attr.map_fd = fd;
234         attr.key = ptr_to_u64(key);
235         attr.value = ptr_to_u64(value);
236         attr.flags = flags;
237
238         return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
239 }
240
241 int bpf_map_lookup_elem(int fd, const void *key, void *value)
242 {
243         union bpf_attr attr;
244
245         bzero(&attr, sizeof(attr));
246         attr.map_fd = fd;
247         attr.key = ptr_to_u64(key);
248         attr.value = ptr_to_u64(value);
249
250         return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
251 }
252
253 int bpf_map_delete_elem(int fd, const void *key)
254 {
255         union bpf_attr attr;
256
257         bzero(&attr, sizeof(attr));
258         attr.map_fd = fd;
259         attr.key = ptr_to_u64(key);
260
261         return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
262 }
263
264 int bpf_map_get_next_key(int fd, const void *key, void *next_key)
265 {
266         union bpf_attr attr;
267
268         bzero(&attr, sizeof(attr));
269         attr.map_fd = fd;
270         attr.key = ptr_to_u64(key);
271         attr.next_key = ptr_to_u64(next_key);
272
273         return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
274 }
275
276 int bpf_obj_pin(int fd, const char *pathname)
277 {
278         union bpf_attr attr;
279
280         bzero(&attr, sizeof(attr));
281         attr.pathname = ptr_to_u64((void *)pathname);
282         attr.bpf_fd = fd;
283
284         return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
285 }
286
287 int bpf_obj_get(const char *pathname)
288 {
289         union bpf_attr attr;
290
291         bzero(&attr, sizeof(attr));
292         attr.pathname = ptr_to_u64((void *)pathname);
293
294         return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
295 }
296
297 int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
298                     unsigned int flags)
299 {
300         union bpf_attr attr;
301
302         bzero(&attr, sizeof(attr));
303         attr.target_fd     = target_fd;
304         attr.attach_bpf_fd = prog_fd;
305         attr.attach_type   = type;
306         attr.attach_flags  = flags;
307
308         return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
309 }
310
311 int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
312 {
313         union bpf_attr attr;
314
315         bzero(&attr, sizeof(attr));
316         attr.target_fd   = target_fd;
317         attr.attach_type = type;
318
319         return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
320 }
321
322 int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
323 {
324         union bpf_attr attr;
325
326         bzero(&attr, sizeof(attr));
327         attr.target_fd   = target_fd;
328         attr.attach_bpf_fd = prog_fd;
329         attr.attach_type = type;
330
331         return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
332 }
333
334 int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
335                    __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
336 {
337         union bpf_attr attr;
338         int ret;
339
340         bzero(&attr, sizeof(attr));
341         attr.query.target_fd    = target_fd;
342         attr.query.attach_type  = type;
343         attr.query.query_flags  = query_flags;
344         attr.query.prog_cnt     = *prog_cnt;
345         attr.query.prog_ids     = ptr_to_u64(prog_ids);
346
347         ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr));
348         if (attach_flags)
349                 *attach_flags = attr.query.attach_flags;
350         *prog_cnt = attr.query.prog_cnt;
351         return ret;
352 }
353
354 int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size,
355                       void *data_out, __u32 *size_out, __u32 *retval,
356                       __u32 *duration)
357 {
358         union bpf_attr attr;
359         int ret;
360
361         bzero(&attr, sizeof(attr));
362         attr.test.prog_fd = prog_fd;
363         attr.test.data_in = ptr_to_u64(data);
364         attr.test.data_out = ptr_to_u64(data_out);
365         attr.test.data_size_in = size;
366         attr.test.repeat = repeat;
367
368         ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
369         if (size_out)
370                 *size_out = attr.test.data_size_out;
371         if (retval)
372                 *retval = attr.test.retval;
373         if (duration)
374                 *duration = attr.test.duration;
375         return ret;
376 }
377
378 int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
379 {
380         union bpf_attr attr;
381         int err;
382
383         bzero(&attr, sizeof(attr));
384         attr.start_id = start_id;
385
386         err = sys_bpf(BPF_PROG_GET_NEXT_ID, &attr, sizeof(attr));
387         if (!err)
388                 *next_id = attr.next_id;
389
390         return err;
391 }
392
393 int bpf_map_get_next_id(__u32 start_id, __u32 *next_id)
394 {
395         union bpf_attr attr;
396         int err;
397
398         bzero(&attr, sizeof(attr));
399         attr.start_id = start_id;
400
401         err = sys_bpf(BPF_MAP_GET_NEXT_ID, &attr, sizeof(attr));
402         if (!err)
403                 *next_id = attr.next_id;
404
405         return err;
406 }
407
408 int bpf_prog_get_fd_by_id(__u32 id)
409 {
410         union bpf_attr attr;
411
412         bzero(&attr, sizeof(attr));
413         attr.prog_id = id;
414
415         return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
416 }
417
418 int bpf_map_get_fd_by_id(__u32 id)
419 {
420         union bpf_attr attr;
421
422         bzero(&attr, sizeof(attr));
423         attr.map_id = id;
424
425         return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
426 }
427
428 int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
429 {
430         union bpf_attr attr;
431         int err;
432
433         bzero(&attr, sizeof(attr));
434         attr.info.bpf_fd = prog_fd;
435         attr.info.info_len = *info_len;
436         attr.info.info = ptr_to_u64(info);
437
438         err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
439         if (!err)
440                 *info_len = attr.info.info_len;
441
442         return err;
443 }
444
445 int bpf_raw_tracepoint_open(const char *name, int prog_fd)
446 {
447         union bpf_attr attr;
448
449         bzero(&attr, sizeof(attr));
450         attr.raw_tracepoint.name = ptr_to_u64(name);
451         attr.raw_tracepoint.prog_fd = prog_fd;
452
453         return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
454 }
455
456 int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
457 {
458         struct sockaddr_nl sa;
459         int sock, seq = 0, len, ret = -1;
460         char buf[4096];
461         struct nlattr *nla, *nla_xdp;
462         struct {
463                 struct nlmsghdr  nh;
464                 struct ifinfomsg ifinfo;
465                 char             attrbuf[64];
466         } req;
467         struct nlmsghdr *nh;
468         struct nlmsgerr *err;
469         socklen_t addrlen;
470         int one = 1;
471
472         memset(&sa, 0, sizeof(sa));
473         sa.nl_family = AF_NETLINK;
474
475         sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
476         if (sock < 0) {
477                 return -errno;
478         }
479
480         if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
481                        &one, sizeof(one)) < 0) {
482                 fprintf(stderr, "Netlink error reporting not supported\n");
483         }
484
485         if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
486                 ret = -errno;
487                 goto cleanup;
488         }
489
490         addrlen = sizeof(sa);
491         if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
492                 ret = -errno;
493                 goto cleanup;
494         }
495
496         if (addrlen != sizeof(sa)) {
497                 ret = -LIBBPF_ERRNO__INTERNAL;
498                 goto cleanup;
499         }
500
501         memset(&req, 0, sizeof(req));
502         req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
503         req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
504         req.nh.nlmsg_type = RTM_SETLINK;
505         req.nh.nlmsg_pid = 0;
506         req.nh.nlmsg_seq = ++seq;
507         req.ifinfo.ifi_family = AF_UNSPEC;
508         req.ifinfo.ifi_index = ifindex;
509
510         /* started nested attribute for XDP */
511         nla = (struct nlattr *)(((char *)&req)
512                                 + NLMSG_ALIGN(req.nh.nlmsg_len));
513         nla->nla_type = NLA_F_NESTED | IFLA_XDP;
514         nla->nla_len = NLA_HDRLEN;
515
516         /* add XDP fd */
517         nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
518         nla_xdp->nla_type = IFLA_XDP_FD;
519         nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
520         memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
521         nla->nla_len += nla_xdp->nla_len;
522
523         /* if user passed in any flags, add those too */
524         if (flags) {
525                 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
526                 nla_xdp->nla_type = IFLA_XDP_FLAGS;
527                 nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
528                 memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
529                 nla->nla_len += nla_xdp->nla_len;
530         }
531
532         req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
533
534         if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
535                 ret = -errno;
536                 goto cleanup;
537         }
538
539         len = recv(sock, buf, sizeof(buf), 0);
540         if (len < 0) {
541                 ret = -errno;
542                 goto cleanup;
543         }
544
545         for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
546              nh = NLMSG_NEXT(nh, len)) {
547                 if (nh->nlmsg_pid != sa.nl_pid) {
548                         ret = -LIBBPF_ERRNO__WRNGPID;
549                         goto cleanup;
550                 }
551                 if (nh->nlmsg_seq != seq) {
552                         ret = -LIBBPF_ERRNO__INVSEQ;
553                         goto cleanup;
554                 }
555                 switch (nh->nlmsg_type) {
556                 case NLMSG_ERROR:
557                         err = (struct nlmsgerr *)NLMSG_DATA(nh);
558                         if (!err->error)
559                                 continue;
560                         ret = err->error;
561                         nla_dump_errormsg(nh);
562                         goto cleanup;
563                 case NLMSG_DONE:
564                         break;
565                 default:
566                         break;
567                 }
568         }
569
570         ret = 0;
571
572 cleanup:
573         close(sock);
574         return ret;
575 }