1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "bpf-dlopen.h"
4 #include "dlfcn-util.h"
9 /* libbpf changed types of function prototypes around, so we need to disable some type checking for older
10 * libbpf. We consider everything older than 0.7 too old for accurate type checks. */
11 #if defined(__LIBBPF_CURRENT_VERSION_GEQ)
12 #if __LIBBPF_CURRENT_VERSION_GEQ(0, 7)
13 #define MODERN_LIBBPF 1
16 #if !defined(MODERN_LIBBPF)
17 #define MODERN_LIBBPF 0
20 DLSYM_PROTOTYPE(bpf_link__destroy
) = NULL
;
21 DLSYM_PROTOTYPE(bpf_link__fd
) = NULL
;
22 DLSYM_PROTOTYPE(bpf_link__open
) = NULL
;
23 DLSYM_PROTOTYPE(bpf_link__pin
) = NULL
;
24 DLSYM_PROTOTYPE(bpf_map__fd
) = NULL
;
25 DLSYM_PROTOTYPE(bpf_map__name
) = NULL
;
26 DLSYM_PROTOTYPE(bpf_map__set_inner_map_fd
) = NULL
;
27 DLSYM_PROTOTYPE(bpf_map__set_max_entries
) = NULL
;
28 DLSYM_PROTOTYPE(bpf_map__set_pin_path
) = NULL
;
29 DLSYM_PROTOTYPE(bpf_map_delete_elem
) = NULL
;
30 DLSYM_PROTOTYPE(bpf_map_get_fd_by_id
) = NULL
;
31 DLSYM_PROTOTYPE(bpf_map_lookup_elem
) = NULL
;
32 DLSYM_PROTOTYPE(bpf_map_update_elem
) = NULL
;
33 DLSYM_PROTOTYPE(bpf_object__attach_skeleton
) = NULL
;
34 DLSYM_PROTOTYPE(bpf_object__destroy_skeleton
) = NULL
;
35 DLSYM_PROTOTYPE(bpf_object__detach_skeleton
) = NULL
;
36 DLSYM_PROTOTYPE(bpf_object__load_skeleton
) = NULL
;
37 DLSYM_PROTOTYPE(bpf_object__name
) = NULL
;
38 DLSYM_PROTOTYPE(bpf_object__open_skeleton
) = NULL
;
39 DLSYM_PROTOTYPE(bpf_object__pin_maps
) = NULL
;
40 DLSYM_PROTOTYPE(bpf_program__attach
) = NULL
;
41 DLSYM_PROTOTYPE(bpf_program__attach_cgroup
) = NULL
;
42 DLSYM_PROTOTYPE(bpf_program__attach_lsm
) = NULL
;
43 DLSYM_PROTOTYPE(bpf_program__name
) = NULL
;
44 DLSYM_PROTOTYPE(libbpf_get_error
) = NULL
;
45 DLSYM_PROTOTYPE(libbpf_set_print
) = NULL
;
46 DLSYM_PROTOTYPE(ring_buffer__epoll_fd
) = NULL
;
47 DLSYM_PROTOTYPE(ring_buffer__free
) = NULL
;
48 DLSYM_PROTOTYPE(ring_buffer__new
) = NULL
;
49 DLSYM_PROTOTYPE(ring_buffer__poll
) = NULL
;
51 /* new symbols available from libbpf 0.7.0 */
52 int (*sym_bpf_map_create
)(enum bpf_map_type
, const char *, __u32
, __u32
, __u32
, const struct bpf_map_create_opts
*);
53 struct bpf_map
* (*sym_bpf_object__next_map
)(const struct bpf_object
*obj
, const struct bpf_map
*map
);
55 /* compat symbols removed in libbpf 1.0 */
56 int (*sym_bpf_create_map
)(enum bpf_map_type
, int key_size
, int value_size
, int max_entries
, __u32 map_flags
);
59 static int bpf_print_func(enum libbpf_print_level level
, const char *fmt
, va_list ap
) {
61 /* libbpf logs a lot of details at its debug level, which we don't need to see. */
62 if (level
== LIBBPF_DEBUG
)
65 /* All other levels are downgraded to LOG_DEBUG */
67 /* errno is used here, on the assumption that if the log message uses %m, errno will be set to
68 * something useful. Otherwise, it shouldn't matter, we may pass 0 or some bogus value. */
69 return log_internalv(LOG_DEBUG
, errno
, NULL
, 0, NULL
, fmt
, ap
);
72 int dlopen_bpf_full(int log_level
) {
73 static int cached
= 0;
80 ELF_NOTE_DLOPEN("bpf",
81 "Support firewalling and sandboxing with BPF",
82 ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED
,
83 "libbpf.so.1", "libbpf.so.0");
85 DISABLE_WARNING_DEPRECATED_DECLARATIONS
;
87 dl
= dlopen("libbpf.so.1", RTLD_NOW
|RTLD_NODELETE
);
89 /* libbpf < 1.0.0 (we rely on 0.1.0+) provide most symbols we care about, but
90 * unfortunately not all until 0.7.0. See bpf-compat.h for more details.
91 * Once we consider we can assume 0.7+ is present we can just use the same symbol
92 * list for both files, and when we assume 1.0+ is present we can remove this dlopen */
93 dl
= dlopen("libbpf.so.0", RTLD_NOW
|RTLD_NODELETE
);
95 return cached
= log_full_errno(log_level
, SYNTHETIC_ERRNO(EOPNOTSUPP
),
96 "Neither libbpf.so.1 nor libbpf.so.0 are installed, cgroup BPF features disabled: %s",
99 log_debug("Loaded 'libbpf.so.0' via dlopen()");
101 /* symbols deprecated in 1.0 we use as compat */
102 r
= dlsym_many_or_warn(
105 /* Don't exist anymore in new libbpf, hence cannot type check them */
106 DLSYM_ARG_FORCE(bpf_create_map
)
108 DLSYM_ARG(bpf_create_map
)
112 /* NB: we don't try to load bpf_object__next_map() on old versions */
114 log_debug("Loaded 'libbpf.so.1' via dlopen()");
116 /* symbols available from 0.7.0 */
117 r
= dlsym_many_or_warn(
120 DLSYM_ARG(bpf_map_create
),
121 DLSYM_ARG(bpf_object__next_map
)
123 /* These symbols did not exist in old libbpf, hence we cannot type check them */
124 DLSYM_ARG_FORCE(bpf_map_create
),
125 DLSYM_ARG_FORCE(bpf_object__next_map
)
130 return cached
= log_full_errno(log_level
, r
, "Failed to load libbpf symbols, cgroup BPF features disabled: %m");
132 r
= dlsym_many_or_warn(
134 DLSYM_ARG(bpf_link__destroy
),
135 DLSYM_ARG(bpf_link__fd
),
136 DLSYM_ARG(bpf_link__open
),
137 DLSYM_ARG(bpf_link__pin
),
138 DLSYM_ARG(bpf_map__fd
),
139 DLSYM_ARG(bpf_map__name
),
140 DLSYM_ARG(bpf_map__set_inner_map_fd
),
141 DLSYM_ARG(bpf_map__set_max_entries
),
142 DLSYM_ARG(bpf_map__set_pin_path
),
143 DLSYM_ARG(bpf_map_delete_elem
),
144 DLSYM_ARG(bpf_map_get_fd_by_id
),
145 DLSYM_ARG(bpf_map_lookup_elem
),
146 DLSYM_ARG(bpf_map_update_elem
),
147 DLSYM_ARG(bpf_object__attach_skeleton
),
148 DLSYM_ARG(bpf_object__destroy_skeleton
),
149 DLSYM_ARG(bpf_object__detach_skeleton
),
150 DLSYM_ARG(bpf_object__load_skeleton
),
151 DLSYM_ARG(bpf_object__name
),
152 DLSYM_ARG(bpf_object__open_skeleton
),
153 DLSYM_ARG(bpf_object__pin_maps
),
155 DLSYM_ARG(bpf_program__attach
),
156 DLSYM_ARG(bpf_program__attach_cgroup
),
157 DLSYM_ARG(bpf_program__attach_lsm
),
159 /* libbpf added a "const" to function parameters where it should not have, ignore this type incompatibility */
160 DLSYM_ARG_FORCE(bpf_program__attach
),
161 DLSYM_ARG_FORCE(bpf_program__attach_cgroup
),
162 DLSYM_ARG_FORCE(bpf_program__attach_lsm
),
164 DLSYM_ARG(bpf_program__name
),
165 DLSYM_ARG(libbpf_get_error
),
166 DLSYM_ARG(libbpf_set_print
),
167 DLSYM_ARG(ring_buffer__epoll_fd
),
168 DLSYM_ARG(ring_buffer__free
),
169 DLSYM_ARG(ring_buffer__new
),
170 DLSYM_ARG(ring_buffer__poll
));
172 return cached
= log_full_errno(log_level
, r
, "Failed to load libbpf symbols, cgroup BPF features disabled: %m");
174 /* We set the print helper unconditionally. Otherwise libbpf will emit not useful log messages. */
175 (void) sym_libbpf_set_print(bpf_print_func
);
179 return cached
= true;
182 int bpf_get_error_translated(const void *ptr
) {
185 r
= sym_libbpf_get_error(ptr
);
189 /* Workaround for kernel bug, BPF returns an internal error instead of translating it, until
191 * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/errno.h?h=v6.9&id=a38297e3fb012ddfa7ce0321a7e5a8daeb1872b6#n27
201 int dlopen_bpf_full(int log_level
) {
202 return log_once_errno(log_level
, SYNTHETIC_ERRNO(EOPNOTSUPP
),
203 "libbpf support is not compiled in, cgroup BPF features disabled.");