1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2020 Facebook */
3 #include <errno.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <sys/resource.h>
10 #include <bpf/libbpf.h>
11 #include <bpf/bpf.h>
12 #include <sys/mount.h>
13 #include "iterators.skel.h"
14 #include "bpf_preload_common.h"
15 
16 int to_kernel = -1;
17 int from_kernel = 0;
18 
send_link_to_kernel(struct bpf_link * link,const char * link_name)19 static int send_link_to_kernel(struct bpf_link *link, const char *link_name)
20 {
21 	struct bpf_preload_info obj = {};
22 	struct bpf_link_info info = {};
23 	__u32 info_len = sizeof(info);
24 	int err;
25 
26 	err = bpf_obj_get_info_by_fd(bpf_link__fd(link), &info, &info_len);
27 	if (err)
28 		return err;
29 	obj.link_id = info.id;
30 	if (strlen(link_name) >= sizeof(obj.link_name))
31 		return -E2BIG;
32 	strcpy(obj.link_name, link_name);
33 	if (write(to_kernel, &obj, sizeof(obj)) != sizeof(obj))
34 		return -EPIPE;
35 	return 0;
36 }
37 
main(int argc,char ** argv)38 int main(int argc, char **argv)
39 {
40 	struct rlimit rlim = { RLIM_INFINITY, RLIM_INFINITY };
41 	struct iterators_bpf *skel;
42 	int err, magic;
43 	int debug_fd;
44 
45 	debug_fd = open("/dev/console", O_WRONLY | O_NOCTTY | O_CLOEXEC);
46 	if (debug_fd < 0)
47 		return 1;
48 	to_kernel = dup(1);
49 	close(1);
50 	dup(debug_fd);
51 	/* now stdin and stderr point to /dev/console */
52 
53 	read(from_kernel, &magic, sizeof(magic));
54 	if (magic != BPF_PRELOAD_START) {
55 		printf("bad start magic %d\n", magic);
56 		return 1;
57 	}
58 	setrlimit(RLIMIT_MEMLOCK, &rlim);
59 	/* libbpf opens BPF object and loads it into the kernel */
60 	skel = iterators_bpf__open_and_load();
61 	if (!skel) {
62 		/* iterators.skel.h is little endian.
63 		 * libbpf doesn't support automatic little->big conversion
64 		 * of BPF bytecode yet.
65 		 * The program load will fail in such case.
66 		 */
67 		printf("Failed load could be due to wrong endianness\n");
68 		return 1;
69 	}
70 	err = iterators_bpf__attach(skel);
71 	if (err)
72 		goto cleanup;
73 
74 	/* send two bpf_link IDs with names to the kernel */
75 	err = send_link_to_kernel(skel->links.dump_bpf_map, "maps.debug");
76 	if (err)
77 		goto cleanup;
78 	err = send_link_to_kernel(skel->links.dump_bpf_prog, "progs.debug");
79 	if (err)
80 		goto cleanup;
81 
82 	/* The kernel will proceed with pinnging the links in bpffs.
83 	 * UMD will wait on read from pipe.
84 	 */
85 	read(from_kernel, &magic, sizeof(magic));
86 	if (magic != BPF_PRELOAD_END) {
87 		printf("bad final magic %d\n", magic);
88 		err = -EINVAL;
89 	}
90 cleanup:
91 	iterators_bpf__destroy(skel);
92 
93 	return err != 0;
94 }
95