bpf.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419
  1. // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
  2. /*
  3. * common eBPF ELF operations.
  4. *
  5. * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
  6. * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
  7. * Copyright (C) 2015 Huawei Inc.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License (not later!)
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this program; if not, see <http://www.gnu.org/licenses>
  21. */
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <memory.h>
  25. #include <unistd.h>
  26. #include <asm/unistd.h>
  27. #include <errno.h>
  28. #include <linux/bpf.h>
  29. #include <linux/filter.h>
  30. #include <linux/kernel.h>
  31. #include <limits.h>
  32. #include <sys/resource.h>
  33. #include "bpf.h"
  34. #include "libbpf.h"
  35. #include "libbpf_internal.h"
  36. /*
  37. * When building perf, unistd.h is overridden. __NR_bpf is
  38. * required to be defined explicitly.
  39. */
  40. #ifndef __NR_bpf
  41. # if defined(__i386__)
  42. # define __NR_bpf 357
  43. # elif defined(__x86_64__)
  44. # define __NR_bpf 321
  45. # elif defined(__aarch64__)
  46. # define __NR_bpf 280
  47. # elif defined(__sparc__)
  48. # define __NR_bpf 349
  49. # elif defined(__s390__)
  50. # define __NR_bpf 351
  51. # elif defined(__arc__)
  52. # define __NR_bpf 280
  53. # elif defined(__mips__) && defined(_ABIO32)
  54. # define __NR_bpf 4355
  55. # elif defined(__mips__) && defined(_ABIN32)
  56. # define __NR_bpf 6319
  57. # elif defined(__mips__) && defined(_ABI64)
  58. # define __NR_bpf 5315
  59. # else
  60. # error __NR_bpf not defined. libbpf does not support your arch.
  61. # endif
  62. #endif
  63. static inline __u64 ptr_to_u64(const void *ptr)
  64. {
  65. return (__u64) (unsigned long) ptr;
  66. }
  67. static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
  68. unsigned int size)
  69. {
  70. return syscall(__NR_bpf, cmd, attr, size);
  71. }
  72. static inline int sys_bpf_fd(enum bpf_cmd cmd, union bpf_attr *attr,
  73. unsigned int size)
  74. {
  75. int fd;
  76. fd = sys_bpf(cmd, attr, size);
  77. return ensure_good_fd(fd);
  78. }
  79. int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts)
  80. {
  81. int fd;
  82. do {
  83. fd = sys_bpf_fd(BPF_PROG_LOAD, attr, size);
  84. } while (fd < 0 && errno == EAGAIN && --attempts > 0);
  85. return fd;
  86. }
  87. /* Probe whether kernel switched from memlock-based (RLIMIT_MEMLOCK) to
  88. * memcg-based memory accounting for BPF maps and progs. This was done in [0].
  89. * We use the support for bpf_ktime_get_coarse_ns() helper, which was added in
  90. * the same 5.11 Linux release ([1]), to detect memcg-based accounting for BPF.
  91. *
  92. * [0] https://lore.kernel.org/bpf/20201201215900.3569844-1-guro@fb.com/
  93. * [1] d05512618056 ("bpf: Add bpf_ktime_get_coarse_ns helper")
  94. */
  95. int probe_memcg_account(int token_fd)
  96. {
  97. const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd);
  98. struct bpf_insn insns[] = {
  99. BPF_EMIT_CALL(BPF_FUNC_ktime_get_coarse_ns),
  100. BPF_EXIT_INSN(),
  101. };
  102. size_t insn_cnt = ARRAY_SIZE(insns);
  103. union bpf_attr attr;
  104. int prog_fd;
  105. /* attempt loading freplace trying to use custom BTF */
  106. memset(&attr, 0, attr_sz);
  107. attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
  108. attr.insns = ptr_to_u64(insns);
  109. attr.insn_cnt = insn_cnt;
  110. attr.license = ptr_to_u64("GPL");
  111. attr.prog_token_fd = token_fd;
  112. if (token_fd)
  113. attr.prog_flags |= BPF_F_TOKEN_FD;
  114. prog_fd = sys_bpf_fd(BPF_PROG_LOAD, &attr, attr_sz);
  115. if (prog_fd >= 0) {
  116. close(prog_fd);
  117. return 1;
  118. }
  119. return 0;
  120. }
  121. static bool memlock_bumped;
  122. static rlim_t memlock_rlim = RLIM_INFINITY;
  123. int libbpf_set_memlock_rlim(size_t memlock_bytes)
  124. {
  125. if (memlock_bumped)
  126. return libbpf_err(-EBUSY);
  127. memlock_rlim = memlock_bytes;
  128. return 0;
  129. }
  130. int bump_rlimit_memlock(void)
  131. {
  132. struct rlimit rlim;
  133. /* if kernel supports memcg-based accounting, skip bumping RLIMIT_MEMLOCK */
  134. if (memlock_bumped || feat_supported(NULL, FEAT_MEMCG_ACCOUNT))
  135. return 0;
  136. memlock_bumped = true;
  137. /* zero memlock_rlim disables auto-bumping RLIMIT_MEMLOCK */
  138. if (memlock_rlim == 0)
  139. return 0;
  140. rlim.rlim_cur = rlim.rlim_max = memlock_rlim;
  141. if (setrlimit(RLIMIT_MEMLOCK, &rlim))
  142. return -errno;
  143. return 0;
  144. }
  145. int bpf_map_create(enum bpf_map_type map_type,
  146. const char *map_name,
  147. __u32 key_size,
  148. __u32 value_size,
  149. __u32 max_entries,
  150. const struct bpf_map_create_opts *opts)
  151. {
  152. const size_t attr_sz = offsetofend(union bpf_attr, excl_prog_hash_size);
  153. union bpf_attr attr;
  154. int fd;
  155. bump_rlimit_memlock();
  156. memset(&attr, 0, attr_sz);
  157. if (!OPTS_VALID(opts, bpf_map_create_opts))
  158. return libbpf_err(-EINVAL);
  159. attr.map_type = map_type;
  160. if (map_name && feat_supported(NULL, FEAT_PROG_NAME))
  161. libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name));
  162. attr.key_size = key_size;
  163. attr.value_size = value_size;
  164. attr.max_entries = max_entries;
  165. attr.btf_fd = OPTS_GET(opts, btf_fd, 0);
  166. attr.btf_key_type_id = OPTS_GET(opts, btf_key_type_id, 0);
  167. attr.btf_value_type_id = OPTS_GET(opts, btf_value_type_id, 0);
  168. attr.btf_vmlinux_value_type_id = OPTS_GET(opts, btf_vmlinux_value_type_id, 0);
  169. attr.value_type_btf_obj_fd = OPTS_GET(opts, value_type_btf_obj_fd, 0);
  170. attr.inner_map_fd = OPTS_GET(opts, inner_map_fd, 0);
  171. attr.map_flags = OPTS_GET(opts, map_flags, 0);
  172. attr.map_extra = OPTS_GET(opts, map_extra, 0);
  173. attr.numa_node = OPTS_GET(opts, numa_node, 0);
  174. attr.map_ifindex = OPTS_GET(opts, map_ifindex, 0);
  175. attr.map_token_fd = OPTS_GET(opts, token_fd, 0);
  176. attr.excl_prog_hash = ptr_to_u64(OPTS_GET(opts, excl_prog_hash, NULL));
  177. attr.excl_prog_hash_size = OPTS_GET(opts, excl_prog_hash_size, 0);
  178. fd = sys_bpf_fd(BPF_MAP_CREATE, &attr, attr_sz);
  179. return libbpf_err_errno(fd);
  180. }
  181. static void *
  182. alloc_zero_tailing_info(const void *orecord, __u32 cnt,
  183. __u32 actual_rec_size, __u32 expected_rec_size)
  184. {
  185. __u64 info_len = (__u64)actual_rec_size * cnt;
  186. void *info, *nrecord;
  187. int i;
  188. info = malloc(info_len);
  189. if (!info)
  190. return NULL;
  191. /* zero out bytes kernel does not understand */
  192. nrecord = info;
  193. for (i = 0; i < cnt; i++) {
  194. memcpy(nrecord, orecord, expected_rec_size);
  195. memset(nrecord + expected_rec_size, 0,
  196. actual_rec_size - expected_rec_size);
  197. orecord += actual_rec_size;
  198. nrecord += actual_rec_size;
  199. }
  200. return info;
  201. }
  202. int bpf_prog_load(enum bpf_prog_type prog_type,
  203. const char *prog_name, const char *license,
  204. const struct bpf_insn *insns, size_t insn_cnt,
  205. struct bpf_prog_load_opts *opts)
  206. {
  207. const size_t attr_sz = offsetofend(union bpf_attr, keyring_id);
  208. void *finfo = NULL, *linfo = NULL;
  209. const char *func_info, *line_info;
  210. __u32 log_size, log_level, attach_prog_fd, attach_btf_obj_fd;
  211. __u32 func_info_rec_size, line_info_rec_size;
  212. int fd, attempts;
  213. union bpf_attr attr;
  214. char *log_buf;
  215. bump_rlimit_memlock();
  216. if (!OPTS_VALID(opts, bpf_prog_load_opts))
  217. return libbpf_err(-EINVAL);
  218. attempts = OPTS_GET(opts, attempts, 0);
  219. if (attempts < 0)
  220. return libbpf_err(-EINVAL);
  221. if (attempts == 0)
  222. attempts = PROG_LOAD_ATTEMPTS;
  223. memset(&attr, 0, attr_sz);
  224. attr.prog_type = prog_type;
  225. attr.expected_attach_type = OPTS_GET(opts, expected_attach_type, 0);
  226. attr.prog_btf_fd = OPTS_GET(opts, prog_btf_fd, 0);
  227. attr.prog_flags = OPTS_GET(opts, prog_flags, 0);
  228. attr.prog_ifindex = OPTS_GET(opts, prog_ifindex, 0);
  229. attr.kern_version = OPTS_GET(opts, kern_version, 0);
  230. attr.prog_token_fd = OPTS_GET(opts, token_fd, 0);
  231. if (prog_name && feat_supported(NULL, FEAT_PROG_NAME))
  232. libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
  233. attr.license = ptr_to_u64(license);
  234. if (insn_cnt > UINT_MAX)
  235. return libbpf_err(-E2BIG);
  236. attr.insns = ptr_to_u64(insns);
  237. attr.insn_cnt = (__u32)insn_cnt;
  238. attach_prog_fd = OPTS_GET(opts, attach_prog_fd, 0);
  239. attach_btf_obj_fd = OPTS_GET(opts, attach_btf_obj_fd, 0);
  240. if (attach_prog_fd && attach_btf_obj_fd)
  241. return libbpf_err(-EINVAL);
  242. attr.attach_btf_id = OPTS_GET(opts, attach_btf_id, 0);
  243. if (attach_prog_fd)
  244. attr.attach_prog_fd = attach_prog_fd;
  245. else
  246. attr.attach_btf_obj_fd = attach_btf_obj_fd;
  247. log_buf = OPTS_GET(opts, log_buf, NULL);
  248. log_size = OPTS_GET(opts, log_size, 0);
  249. log_level = OPTS_GET(opts, log_level, 0);
  250. if (!!log_buf != !!log_size)
  251. return libbpf_err(-EINVAL);
  252. func_info_rec_size = OPTS_GET(opts, func_info_rec_size, 0);
  253. func_info = OPTS_GET(opts, func_info, NULL);
  254. attr.func_info_rec_size = func_info_rec_size;
  255. attr.func_info = ptr_to_u64(func_info);
  256. attr.func_info_cnt = OPTS_GET(opts, func_info_cnt, 0);
  257. line_info_rec_size = OPTS_GET(opts, line_info_rec_size, 0);
  258. line_info = OPTS_GET(opts, line_info, NULL);
  259. attr.line_info_rec_size = line_info_rec_size;
  260. attr.line_info = ptr_to_u64(line_info);
  261. attr.line_info_cnt = OPTS_GET(opts, line_info_cnt, 0);
  262. attr.fd_array = ptr_to_u64(OPTS_GET(opts, fd_array, NULL));
  263. attr.fd_array_cnt = OPTS_GET(opts, fd_array_cnt, 0);
  264. if (log_level) {
  265. attr.log_buf = ptr_to_u64(log_buf);
  266. attr.log_size = log_size;
  267. attr.log_level = log_level;
  268. }
  269. fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
  270. OPTS_SET(opts, log_true_size, attr.log_true_size);
  271. if (fd >= 0)
  272. return fd;
  273. /* After bpf_prog_load, the kernel may modify certain attributes
  274. * to give user space a hint how to deal with loading failure.
  275. * Check to see whether we can make some changes and load again.
  276. */
  277. while (errno == E2BIG && (!finfo || !linfo)) {
  278. if (!finfo && attr.func_info_cnt &&
  279. attr.func_info_rec_size < func_info_rec_size) {
  280. /* try with corrected func info records */
  281. finfo = alloc_zero_tailing_info(func_info,
  282. attr.func_info_cnt,
  283. func_info_rec_size,
  284. attr.func_info_rec_size);
  285. if (!finfo) {
  286. errno = E2BIG;
  287. goto done;
  288. }
  289. attr.func_info = ptr_to_u64(finfo);
  290. attr.func_info_rec_size = func_info_rec_size;
  291. } else if (!linfo && attr.line_info_cnt &&
  292. attr.line_info_rec_size < line_info_rec_size) {
  293. linfo = alloc_zero_tailing_info(line_info,
  294. attr.line_info_cnt,
  295. line_info_rec_size,
  296. attr.line_info_rec_size);
  297. if (!linfo) {
  298. errno = E2BIG;
  299. goto done;
  300. }
  301. attr.line_info = ptr_to_u64(linfo);
  302. attr.line_info_rec_size = line_info_rec_size;
  303. } else {
  304. break;
  305. }
  306. fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
  307. OPTS_SET(opts, log_true_size, attr.log_true_size);
  308. if (fd >= 0)
  309. goto done;
  310. }
  311. if (log_level == 0 && log_buf) {
  312. /* log_level == 0 with non-NULL log_buf requires retrying on error
  313. * with log_level == 1 and log_buf/log_buf_size set, to get details of
  314. * failure
  315. */
  316. attr.log_buf = ptr_to_u64(log_buf);
  317. attr.log_size = log_size;
  318. attr.log_level = 1;
  319. fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
  320. OPTS_SET(opts, log_true_size, attr.log_true_size);
  321. }
  322. done:
  323. /* free() doesn't affect errno, so we don't need to restore it */
  324. free(finfo);
  325. free(linfo);
  326. return libbpf_err_errno(fd);
  327. }
  328. int bpf_map_update_elem(int fd, const void *key, const void *value,
  329. __u64 flags)
  330. {
  331. const size_t attr_sz = offsetofend(union bpf_attr, flags);
  332. union bpf_attr attr;
  333. int ret;
  334. memset(&attr, 0, attr_sz);
  335. attr.map_fd = fd;
  336. attr.key = ptr_to_u64(key);
  337. attr.value = ptr_to_u64(value);
  338. attr.flags = flags;
  339. ret = sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, attr_sz);
  340. return libbpf_err_errno(ret);
  341. }
  342. int bpf_map_lookup_elem(int fd, const void *key, void *value)
  343. {
  344. const size_t attr_sz = offsetofend(union bpf_attr, flags);
  345. union bpf_attr attr;
  346. int ret;
  347. memset(&attr, 0, attr_sz);
  348. attr.map_fd = fd;
  349. attr.key = ptr_to_u64(key);
  350. attr.value = ptr_to_u64(value);
  351. ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz);
  352. return libbpf_err_errno(ret);
  353. }
  354. int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
  355. {
  356. const size_t attr_sz = offsetofend(union bpf_attr, flags);
  357. union bpf_attr attr;
  358. int ret;
  359. memset(&attr, 0, attr_sz);
  360. attr.map_fd = fd;
  361. attr.key = ptr_to_u64(key);
  362. attr.value = ptr_to_u64(value);
  363. attr.flags = flags;
  364. ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz);
  365. return libbpf_err_errno(ret);
  366. }
  367. int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
  368. {
  369. const size_t attr_sz = offsetofend(union bpf_attr, flags);
  370. union bpf_attr attr;
  371. int ret;
  372. memset(&attr, 0, attr_sz);
  373. attr.map_fd = fd;
  374. attr.key = ptr_to_u64(key);
  375. attr.value = ptr_to_u64(value);
  376. ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz);
  377. return libbpf_err_errno(ret);
  378. }
  379. int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags)
  380. {
  381. const size_t attr_sz = offsetofend(union bpf_attr, flags);
  382. union bpf_attr attr;
  383. int ret;
  384. memset(&attr, 0, attr_sz);
  385. attr.map_fd = fd;
  386. attr.key = ptr_to_u64(key);
  387. attr.value = ptr_to_u64(value);
  388. attr.flags = flags;
  389. ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz);
  390. return libbpf_err_errno(ret);
  391. }
  392. int bpf_map_delete_elem(int fd, const void *key)
  393. {
  394. const size_t attr_sz = offsetofend(union bpf_attr, flags);
  395. union bpf_attr attr;
  396. int ret;
  397. memset(&attr, 0, attr_sz);
  398. attr.map_fd = fd;
  399. attr.key = ptr_to_u64(key);
  400. ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz);
  401. return libbpf_err_errno(ret);
  402. }
  403. int bpf_map_delete_elem_flags(int fd, const void *key, __u64 flags)
  404. {
  405. const size_t attr_sz = offsetofend(union bpf_attr, flags);
  406. union bpf_attr attr;
  407. int ret;
  408. memset(&attr, 0, attr_sz);
  409. attr.map_fd = fd;
  410. attr.key = ptr_to_u64(key);
  411. attr.flags = flags;
  412. ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz);
  413. return libbpf_err_errno(ret);
  414. }
  415. int bpf_map_get_next_key(int fd, const void *key, void *next_key)
  416. {
  417. const size_t attr_sz = offsetofend(union bpf_attr, next_key);
  418. union bpf_attr attr;
  419. int ret;
  420. memset(&attr, 0, attr_sz);
  421. attr.map_fd = fd;
  422. attr.key = ptr_to_u64(key);
  423. attr.next_key = ptr_to_u64(next_key);
  424. ret = sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, attr_sz);
  425. return libbpf_err_errno(ret);
  426. }
  427. int bpf_map_freeze(int fd)
  428. {
  429. const size_t attr_sz = offsetofend(union bpf_attr, map_fd);
  430. union bpf_attr attr;
  431. int ret;
  432. memset(&attr, 0, attr_sz);
  433. attr.map_fd = fd;
  434. ret = sys_bpf(BPF_MAP_FREEZE, &attr, attr_sz);
  435. return libbpf_err_errno(ret);
  436. }
  437. static int bpf_map_batch_common(int cmd, int fd, void *in_batch,
  438. void *out_batch, void *keys, void *values,
  439. __u32 *count,
  440. const struct bpf_map_batch_opts *opts)
  441. {
  442. const size_t attr_sz = offsetofend(union bpf_attr, batch);
  443. union bpf_attr attr;
  444. int ret;
  445. if (!OPTS_VALID(opts, bpf_map_batch_opts))
  446. return libbpf_err(-EINVAL);
  447. memset(&attr, 0, attr_sz);
  448. attr.batch.map_fd = fd;
  449. attr.batch.in_batch = ptr_to_u64(in_batch);
  450. attr.batch.out_batch = ptr_to_u64(out_batch);
  451. attr.batch.keys = ptr_to_u64(keys);
  452. attr.batch.values = ptr_to_u64(values);
  453. attr.batch.count = *count;
  454. attr.batch.elem_flags = OPTS_GET(opts, elem_flags, 0);
  455. attr.batch.flags = OPTS_GET(opts, flags, 0);
  456. ret = sys_bpf(cmd, &attr, attr_sz);
  457. *count = attr.batch.count;
  458. return libbpf_err_errno(ret);
  459. }
  460. int bpf_map_delete_batch(int fd, const void *keys, __u32 *count,
  461. const struct bpf_map_batch_opts *opts)
  462. {
  463. return bpf_map_batch_common(BPF_MAP_DELETE_BATCH, fd, NULL,
  464. NULL, (void *)keys, NULL, count, opts);
  465. }
  466. int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch, void *keys,
  467. void *values, __u32 *count,
  468. const struct bpf_map_batch_opts *opts)
  469. {
  470. return bpf_map_batch_common(BPF_MAP_LOOKUP_BATCH, fd, in_batch,
  471. out_batch, keys, values, count, opts);
  472. }
  473. int bpf_map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch,
  474. void *keys, void *values, __u32 *count,
  475. const struct bpf_map_batch_opts *opts)
  476. {
  477. return bpf_map_batch_common(BPF_MAP_LOOKUP_AND_DELETE_BATCH,
  478. fd, in_batch, out_batch, keys, values,
  479. count, opts);
  480. }
  481. int bpf_map_update_batch(int fd, const void *keys, const void *values, __u32 *count,
  482. const struct bpf_map_batch_opts *opts)
  483. {
  484. return bpf_map_batch_common(BPF_MAP_UPDATE_BATCH, fd, NULL, NULL,
  485. (void *)keys, (void *)values, count, opts);
  486. }
  487. int bpf_obj_pin_opts(int fd, const char *pathname, const struct bpf_obj_pin_opts *opts)
  488. {
  489. const size_t attr_sz = offsetofend(union bpf_attr, path_fd);
  490. union bpf_attr attr;
  491. int ret;
  492. if (!OPTS_VALID(opts, bpf_obj_pin_opts))
  493. return libbpf_err(-EINVAL);
  494. memset(&attr, 0, attr_sz);
  495. attr.path_fd = OPTS_GET(opts, path_fd, 0);
  496. attr.pathname = ptr_to_u64((void *)pathname);
  497. attr.file_flags = OPTS_GET(opts, file_flags, 0);
  498. attr.bpf_fd = fd;
  499. ret = sys_bpf(BPF_OBJ_PIN, &attr, attr_sz);
  500. return libbpf_err_errno(ret);
  501. }
  502. int bpf_obj_pin(int fd, const char *pathname)
  503. {
  504. return bpf_obj_pin_opts(fd, pathname, NULL);
  505. }
  506. int bpf_obj_get(const char *pathname)
  507. {
  508. return bpf_obj_get_opts(pathname, NULL);
  509. }
  510. int bpf_obj_get_opts(const char *pathname, const struct bpf_obj_get_opts *opts)
  511. {
  512. const size_t attr_sz = offsetofend(union bpf_attr, path_fd);
  513. union bpf_attr attr;
  514. int fd;
  515. if (!OPTS_VALID(opts, bpf_obj_get_opts))
  516. return libbpf_err(-EINVAL);
  517. memset(&attr, 0, attr_sz);
  518. attr.path_fd = OPTS_GET(opts, path_fd, 0);
  519. attr.pathname = ptr_to_u64((void *)pathname);
  520. attr.file_flags = OPTS_GET(opts, file_flags, 0);
  521. fd = sys_bpf_fd(BPF_OBJ_GET, &attr, attr_sz);
  522. return libbpf_err_errno(fd);
  523. }
  524. int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
  525. unsigned int flags)
  526. {
  527. DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, opts,
  528. .flags = flags,
  529. );
  530. return bpf_prog_attach_opts(prog_fd, target_fd, type, &opts);
  531. }
  532. int bpf_prog_attach_opts(int prog_fd, int target, enum bpf_attach_type type,
  533. const struct bpf_prog_attach_opts *opts)
  534. {
  535. const size_t attr_sz = offsetofend(union bpf_attr, expected_revision);
  536. __u32 relative_id, flags;
  537. int ret, relative_fd;
  538. union bpf_attr attr;
  539. if (!OPTS_VALID(opts, bpf_prog_attach_opts))
  540. return libbpf_err(-EINVAL);
  541. relative_id = OPTS_GET(opts, relative_id, 0);
  542. relative_fd = OPTS_GET(opts, relative_fd, 0);
  543. flags = OPTS_GET(opts, flags, 0);
  544. /* validate we don't have unexpected combinations of non-zero fields */
  545. if (relative_fd && relative_id)
  546. return libbpf_err(-EINVAL);
  547. memset(&attr, 0, attr_sz);
  548. attr.target_fd = target;
  549. attr.attach_bpf_fd = prog_fd;
  550. attr.attach_type = type;
  551. attr.replace_bpf_fd = OPTS_GET(opts, replace_fd, 0);
  552. attr.expected_revision = OPTS_GET(opts, expected_revision, 0);
  553. if (relative_id) {
  554. attr.attach_flags = flags | BPF_F_ID;
  555. attr.relative_id = relative_id;
  556. } else {
  557. attr.attach_flags = flags;
  558. attr.relative_fd = relative_fd;
  559. }
  560. ret = sys_bpf(BPF_PROG_ATTACH, &attr, attr_sz);
  561. return libbpf_err_errno(ret);
  562. }
  563. int bpf_prog_detach_opts(int prog_fd, int target, enum bpf_attach_type type,
  564. const struct bpf_prog_detach_opts *opts)
  565. {
  566. const size_t attr_sz = offsetofend(union bpf_attr, expected_revision);
  567. __u32 relative_id, flags;
  568. int ret, relative_fd;
  569. union bpf_attr attr;
  570. if (!OPTS_VALID(opts, bpf_prog_detach_opts))
  571. return libbpf_err(-EINVAL);
  572. relative_id = OPTS_GET(opts, relative_id, 0);
  573. relative_fd = OPTS_GET(opts, relative_fd, 0);
  574. flags = OPTS_GET(opts, flags, 0);
  575. /* validate we don't have unexpected combinations of non-zero fields */
  576. if (relative_fd && relative_id)
  577. return libbpf_err(-EINVAL);
  578. memset(&attr, 0, attr_sz);
  579. attr.target_fd = target;
  580. attr.attach_bpf_fd = prog_fd;
  581. attr.attach_type = type;
  582. attr.expected_revision = OPTS_GET(opts, expected_revision, 0);
  583. if (relative_id) {
  584. attr.attach_flags = flags | BPF_F_ID;
  585. attr.relative_id = relative_id;
  586. } else {
  587. attr.attach_flags = flags;
  588. attr.relative_fd = relative_fd;
  589. }
  590. ret = sys_bpf(BPF_PROG_DETACH, &attr, attr_sz);
  591. return libbpf_err_errno(ret);
  592. }
  593. int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
  594. {
  595. return bpf_prog_detach_opts(0, target_fd, type, NULL);
  596. }
  597. int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
  598. {
  599. return bpf_prog_detach_opts(prog_fd, target_fd, type, NULL);
  600. }
  601. int bpf_link_create(int prog_fd, int target_fd,
  602. enum bpf_attach_type attach_type,
  603. const struct bpf_link_create_opts *opts)
  604. {
  605. const size_t attr_sz = offsetofend(union bpf_attr, link_create);
  606. __u32 target_btf_id, iter_info_len, relative_id;
  607. int fd, err, relative_fd;
  608. union bpf_attr attr;
  609. if (!OPTS_VALID(opts, bpf_link_create_opts))
  610. return libbpf_err(-EINVAL);
  611. iter_info_len = OPTS_GET(opts, iter_info_len, 0);
  612. target_btf_id = OPTS_GET(opts, target_btf_id, 0);
  613. /* validate we don't have unexpected combinations of non-zero fields */
  614. if (iter_info_len || target_btf_id) {
  615. if (iter_info_len && target_btf_id)
  616. return libbpf_err(-EINVAL);
  617. if (!OPTS_ZEROED(opts, target_btf_id))
  618. return libbpf_err(-EINVAL);
  619. }
  620. memset(&attr, 0, attr_sz);
  621. attr.link_create.prog_fd = prog_fd;
  622. attr.link_create.target_fd = target_fd;
  623. attr.link_create.attach_type = attach_type;
  624. attr.link_create.flags = OPTS_GET(opts, flags, 0);
  625. if (target_btf_id) {
  626. attr.link_create.target_btf_id = target_btf_id;
  627. goto proceed;
  628. }
  629. switch (attach_type) {
  630. case BPF_TRACE_ITER:
  631. attr.link_create.iter_info = ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0));
  632. attr.link_create.iter_info_len = iter_info_len;
  633. break;
  634. case BPF_PERF_EVENT:
  635. attr.link_create.perf_event.bpf_cookie = OPTS_GET(opts, perf_event.bpf_cookie, 0);
  636. if (!OPTS_ZEROED(opts, perf_event))
  637. return libbpf_err(-EINVAL);
  638. break;
  639. case BPF_TRACE_KPROBE_MULTI:
  640. case BPF_TRACE_KPROBE_SESSION:
  641. attr.link_create.kprobe_multi.flags = OPTS_GET(opts, kprobe_multi.flags, 0);
  642. attr.link_create.kprobe_multi.cnt = OPTS_GET(opts, kprobe_multi.cnt, 0);
  643. attr.link_create.kprobe_multi.syms = ptr_to_u64(OPTS_GET(opts, kprobe_multi.syms, 0));
  644. attr.link_create.kprobe_multi.addrs = ptr_to_u64(OPTS_GET(opts, kprobe_multi.addrs, 0));
  645. attr.link_create.kprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, kprobe_multi.cookies, 0));
  646. if (!OPTS_ZEROED(opts, kprobe_multi))
  647. return libbpf_err(-EINVAL);
  648. break;
  649. case BPF_TRACE_UPROBE_MULTI:
  650. case BPF_TRACE_UPROBE_SESSION:
  651. attr.link_create.uprobe_multi.flags = OPTS_GET(opts, uprobe_multi.flags, 0);
  652. attr.link_create.uprobe_multi.cnt = OPTS_GET(opts, uprobe_multi.cnt, 0);
  653. attr.link_create.uprobe_multi.path = ptr_to_u64(OPTS_GET(opts, uprobe_multi.path, 0));
  654. attr.link_create.uprobe_multi.offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.offsets, 0));
  655. attr.link_create.uprobe_multi.ref_ctr_offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.ref_ctr_offsets, 0));
  656. attr.link_create.uprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, uprobe_multi.cookies, 0));
  657. attr.link_create.uprobe_multi.pid = OPTS_GET(opts, uprobe_multi.pid, 0);
  658. if (!OPTS_ZEROED(opts, uprobe_multi))
  659. return libbpf_err(-EINVAL);
  660. break;
  661. case BPF_TRACE_RAW_TP:
  662. case BPF_TRACE_FENTRY:
  663. case BPF_TRACE_FEXIT:
  664. case BPF_MODIFY_RETURN:
  665. case BPF_TRACE_FSESSION:
  666. case BPF_LSM_MAC:
  667. attr.link_create.tracing.cookie = OPTS_GET(opts, tracing.cookie, 0);
  668. if (!OPTS_ZEROED(opts, tracing))
  669. return libbpf_err(-EINVAL);
  670. break;
  671. case BPF_NETFILTER:
  672. attr.link_create.netfilter.pf = OPTS_GET(opts, netfilter.pf, 0);
  673. attr.link_create.netfilter.hooknum = OPTS_GET(opts, netfilter.hooknum, 0);
  674. attr.link_create.netfilter.priority = OPTS_GET(opts, netfilter.priority, 0);
  675. attr.link_create.netfilter.flags = OPTS_GET(opts, netfilter.flags, 0);
  676. if (!OPTS_ZEROED(opts, netfilter))
  677. return libbpf_err(-EINVAL);
  678. break;
  679. case BPF_TCX_INGRESS:
  680. case BPF_TCX_EGRESS:
  681. relative_fd = OPTS_GET(opts, tcx.relative_fd, 0);
  682. relative_id = OPTS_GET(opts, tcx.relative_id, 0);
  683. if (relative_fd && relative_id)
  684. return libbpf_err(-EINVAL);
  685. if (relative_id) {
  686. attr.link_create.tcx.relative_id = relative_id;
  687. attr.link_create.flags |= BPF_F_ID;
  688. } else {
  689. attr.link_create.tcx.relative_fd = relative_fd;
  690. }
  691. attr.link_create.tcx.expected_revision = OPTS_GET(opts, tcx.expected_revision, 0);
  692. if (!OPTS_ZEROED(opts, tcx))
  693. return libbpf_err(-EINVAL);
  694. break;
  695. case BPF_NETKIT_PRIMARY:
  696. case BPF_NETKIT_PEER:
  697. relative_fd = OPTS_GET(opts, netkit.relative_fd, 0);
  698. relative_id = OPTS_GET(opts, netkit.relative_id, 0);
  699. if (relative_fd && relative_id)
  700. return libbpf_err(-EINVAL);
  701. if (relative_id) {
  702. attr.link_create.netkit.relative_id = relative_id;
  703. attr.link_create.flags |= BPF_F_ID;
  704. } else {
  705. attr.link_create.netkit.relative_fd = relative_fd;
  706. }
  707. attr.link_create.netkit.expected_revision = OPTS_GET(opts, netkit.expected_revision, 0);
  708. if (!OPTS_ZEROED(opts, netkit))
  709. return libbpf_err(-EINVAL);
  710. break;
  711. case BPF_CGROUP_INET_INGRESS:
  712. case BPF_CGROUP_INET_EGRESS:
  713. case BPF_CGROUP_INET_SOCK_CREATE:
  714. case BPF_CGROUP_INET_SOCK_RELEASE:
  715. case BPF_CGROUP_INET4_BIND:
  716. case BPF_CGROUP_INET6_BIND:
  717. case BPF_CGROUP_INET4_POST_BIND:
  718. case BPF_CGROUP_INET6_POST_BIND:
  719. case BPF_CGROUP_INET4_CONNECT:
  720. case BPF_CGROUP_INET6_CONNECT:
  721. case BPF_CGROUP_UNIX_CONNECT:
  722. case BPF_CGROUP_INET4_GETPEERNAME:
  723. case BPF_CGROUP_INET6_GETPEERNAME:
  724. case BPF_CGROUP_UNIX_GETPEERNAME:
  725. case BPF_CGROUP_INET4_GETSOCKNAME:
  726. case BPF_CGROUP_INET6_GETSOCKNAME:
  727. case BPF_CGROUP_UNIX_GETSOCKNAME:
  728. case BPF_CGROUP_UDP4_SENDMSG:
  729. case BPF_CGROUP_UDP6_SENDMSG:
  730. case BPF_CGROUP_UNIX_SENDMSG:
  731. case BPF_CGROUP_UDP4_RECVMSG:
  732. case BPF_CGROUP_UDP6_RECVMSG:
  733. case BPF_CGROUP_UNIX_RECVMSG:
  734. case BPF_CGROUP_SOCK_OPS:
  735. case BPF_CGROUP_DEVICE:
  736. case BPF_CGROUP_SYSCTL:
  737. case BPF_CGROUP_GETSOCKOPT:
  738. case BPF_CGROUP_SETSOCKOPT:
  739. case BPF_LSM_CGROUP:
  740. relative_fd = OPTS_GET(opts, cgroup.relative_fd, 0);
  741. relative_id = OPTS_GET(opts, cgroup.relative_id, 0);
  742. if (relative_fd && relative_id)
  743. return libbpf_err(-EINVAL);
  744. if (relative_id) {
  745. attr.link_create.cgroup.relative_id = relative_id;
  746. attr.link_create.flags |= BPF_F_ID;
  747. } else {
  748. attr.link_create.cgroup.relative_fd = relative_fd;
  749. }
  750. attr.link_create.cgroup.expected_revision =
  751. OPTS_GET(opts, cgroup.expected_revision, 0);
  752. if (!OPTS_ZEROED(opts, cgroup))
  753. return libbpf_err(-EINVAL);
  754. break;
  755. default:
  756. if (!OPTS_ZEROED(opts, flags))
  757. return libbpf_err(-EINVAL);
  758. break;
  759. }
  760. proceed:
  761. fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, attr_sz);
  762. if (fd >= 0)
  763. return fd;
  764. /* we'll get EINVAL if LINK_CREATE doesn't support attaching fentry
  765. * and other similar programs
  766. */
  767. err = -errno;
  768. if (err != -EINVAL)
  769. return libbpf_err(err);
  770. /* if user used features not supported by
  771. * BPF_RAW_TRACEPOINT_OPEN command, then just give up immediately
  772. */
  773. if (attr.link_create.target_fd || attr.link_create.target_btf_id)
  774. return libbpf_err(err);
  775. if (!OPTS_ZEROED(opts, sz))
  776. return libbpf_err(err);
  777. /* otherwise, for few select kinds of programs that can be
  778. * attached using BPF_RAW_TRACEPOINT_OPEN command, try that as
  779. * a fallback for older kernels
  780. */
  781. switch (attach_type) {
  782. case BPF_TRACE_RAW_TP:
  783. case BPF_LSM_MAC:
  784. case BPF_TRACE_FENTRY:
  785. case BPF_TRACE_FEXIT:
  786. case BPF_MODIFY_RETURN:
  787. return bpf_raw_tracepoint_open(NULL, prog_fd);
  788. default:
  789. return libbpf_err(err);
  790. }
  791. }
  792. int bpf_link_detach(int link_fd)
  793. {
  794. const size_t attr_sz = offsetofend(union bpf_attr, link_detach);
  795. union bpf_attr attr;
  796. int ret;
  797. memset(&attr, 0, attr_sz);
  798. attr.link_detach.link_fd = link_fd;
  799. ret = sys_bpf(BPF_LINK_DETACH, &attr, attr_sz);
  800. return libbpf_err_errno(ret);
  801. }
  802. int bpf_link_update(int link_fd, int new_prog_fd,
  803. const struct bpf_link_update_opts *opts)
  804. {
  805. const size_t attr_sz = offsetofend(union bpf_attr, link_update);
  806. union bpf_attr attr;
  807. int ret;
  808. if (!OPTS_VALID(opts, bpf_link_update_opts))
  809. return libbpf_err(-EINVAL);
  810. if (OPTS_GET(opts, old_prog_fd, 0) && OPTS_GET(opts, old_map_fd, 0))
  811. return libbpf_err(-EINVAL);
  812. memset(&attr, 0, attr_sz);
  813. attr.link_update.link_fd = link_fd;
  814. attr.link_update.new_prog_fd = new_prog_fd;
  815. attr.link_update.flags = OPTS_GET(opts, flags, 0);
  816. if (OPTS_GET(opts, old_prog_fd, 0))
  817. attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
  818. else if (OPTS_GET(opts, old_map_fd, 0))
  819. attr.link_update.old_map_fd = OPTS_GET(opts, old_map_fd, 0);
  820. ret = sys_bpf(BPF_LINK_UPDATE, &attr, attr_sz);
  821. return libbpf_err_errno(ret);
  822. }
  823. int bpf_iter_create(int link_fd)
  824. {
  825. const size_t attr_sz = offsetofend(union bpf_attr, iter_create);
  826. union bpf_attr attr;
  827. int fd;
  828. memset(&attr, 0, attr_sz);
  829. attr.iter_create.link_fd = link_fd;
  830. fd = sys_bpf_fd(BPF_ITER_CREATE, &attr, attr_sz);
  831. return libbpf_err_errno(fd);
  832. }
  833. int bpf_prog_query_opts(int target, enum bpf_attach_type type,
  834. struct bpf_prog_query_opts *opts)
  835. {
  836. const size_t attr_sz = offsetofend(union bpf_attr, query);
  837. union bpf_attr attr;
  838. int ret;
  839. if (!OPTS_VALID(opts, bpf_prog_query_opts))
  840. return libbpf_err(-EINVAL);
  841. memset(&attr, 0, attr_sz);
  842. attr.query.target_fd = target;
  843. attr.query.attach_type = type;
  844. attr.query.query_flags = OPTS_GET(opts, query_flags, 0);
  845. attr.query.count = OPTS_GET(opts, count, 0);
  846. attr.query.prog_ids = ptr_to_u64(OPTS_GET(opts, prog_ids, NULL));
  847. attr.query.link_ids = ptr_to_u64(OPTS_GET(opts, link_ids, NULL));
  848. attr.query.prog_attach_flags = ptr_to_u64(OPTS_GET(opts, prog_attach_flags, NULL));
  849. attr.query.link_attach_flags = ptr_to_u64(OPTS_GET(opts, link_attach_flags, NULL));
  850. ret = sys_bpf(BPF_PROG_QUERY, &attr, attr_sz);
  851. OPTS_SET(opts, attach_flags, attr.query.attach_flags);
  852. OPTS_SET(opts, revision, attr.query.revision);
  853. OPTS_SET(opts, count, attr.query.count);
  854. return libbpf_err_errno(ret);
  855. }
  856. int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
  857. __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
  858. {
  859. LIBBPF_OPTS(bpf_prog_query_opts, opts);
  860. int ret;
  861. opts.query_flags = query_flags;
  862. opts.prog_ids = prog_ids;
  863. opts.prog_cnt = *prog_cnt;
  864. ret = bpf_prog_query_opts(target_fd, type, &opts);
  865. if (attach_flags)
  866. *attach_flags = opts.attach_flags;
  867. *prog_cnt = opts.prog_cnt;
  868. return libbpf_err_errno(ret);
  869. }
  870. int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
  871. {
  872. const size_t attr_sz = offsetofend(union bpf_attr, test);
  873. union bpf_attr attr;
  874. int ret;
  875. if (!OPTS_VALID(opts, bpf_test_run_opts))
  876. return libbpf_err(-EINVAL);
  877. memset(&attr, 0, attr_sz);
  878. attr.test.prog_fd = prog_fd;
  879. attr.test.batch_size = OPTS_GET(opts, batch_size, 0);
  880. attr.test.cpu = OPTS_GET(opts, cpu, 0);
  881. attr.test.flags = OPTS_GET(opts, flags, 0);
  882. attr.test.repeat = OPTS_GET(opts, repeat, 0);
  883. attr.test.duration = OPTS_GET(opts, duration, 0);
  884. attr.test.ctx_size_in = OPTS_GET(opts, ctx_size_in, 0);
  885. attr.test.ctx_size_out = OPTS_GET(opts, ctx_size_out, 0);
  886. attr.test.data_size_in = OPTS_GET(opts, data_size_in, 0);
  887. attr.test.data_size_out = OPTS_GET(opts, data_size_out, 0);
  888. attr.test.ctx_in = ptr_to_u64(OPTS_GET(opts, ctx_in, NULL));
  889. attr.test.ctx_out = ptr_to_u64(OPTS_GET(opts, ctx_out, NULL));
  890. attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL));
  891. attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL));
  892. ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, attr_sz);
  893. OPTS_SET(opts, data_size_out, attr.test.data_size_out);
  894. OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out);
  895. OPTS_SET(opts, duration, attr.test.duration);
  896. OPTS_SET(opts, retval, attr.test.retval);
  897. return libbpf_err_errno(ret);
  898. }
  899. static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd)
  900. {
  901. const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
  902. union bpf_attr attr;
  903. int err;
  904. memset(&attr, 0, attr_sz);
  905. attr.start_id = start_id;
  906. err = sys_bpf(cmd, &attr, attr_sz);
  907. if (!err)
  908. *next_id = attr.next_id;
  909. return libbpf_err_errno(err);
  910. }
  911. int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
  912. {
  913. return bpf_obj_get_next_id(start_id, next_id, BPF_PROG_GET_NEXT_ID);
  914. }
  915. int bpf_map_get_next_id(__u32 start_id, __u32 *next_id)
  916. {
  917. return bpf_obj_get_next_id(start_id, next_id, BPF_MAP_GET_NEXT_ID);
  918. }
  919. int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id)
  920. {
  921. return bpf_obj_get_next_id(start_id, next_id, BPF_BTF_GET_NEXT_ID);
  922. }
  923. int bpf_link_get_next_id(__u32 start_id, __u32 *next_id)
  924. {
  925. return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID);
  926. }
  927. int bpf_prog_get_fd_by_id_opts(__u32 id,
  928. const struct bpf_get_fd_by_id_opts *opts)
  929. {
  930. const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
  931. union bpf_attr attr;
  932. int fd;
  933. if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
  934. return libbpf_err(-EINVAL);
  935. memset(&attr, 0, attr_sz);
  936. attr.prog_id = id;
  937. attr.open_flags = OPTS_GET(opts, open_flags, 0);
  938. fd = sys_bpf_fd(BPF_PROG_GET_FD_BY_ID, &attr, attr_sz);
  939. return libbpf_err_errno(fd);
  940. }
  941. int bpf_prog_get_fd_by_id(__u32 id)
  942. {
  943. return bpf_prog_get_fd_by_id_opts(id, NULL);
  944. }
  945. int bpf_map_get_fd_by_id_opts(__u32 id,
  946. const struct bpf_get_fd_by_id_opts *opts)
  947. {
  948. const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
  949. union bpf_attr attr;
  950. int fd;
  951. if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
  952. return libbpf_err(-EINVAL);
  953. memset(&attr, 0, attr_sz);
  954. attr.map_id = id;
  955. attr.open_flags = OPTS_GET(opts, open_flags, 0);
  956. fd = sys_bpf_fd(BPF_MAP_GET_FD_BY_ID, &attr, attr_sz);
  957. return libbpf_err_errno(fd);
  958. }
  959. int bpf_map_get_fd_by_id(__u32 id)
  960. {
  961. return bpf_map_get_fd_by_id_opts(id, NULL);
  962. }
  963. int bpf_btf_get_fd_by_id_opts(__u32 id,
  964. const struct bpf_get_fd_by_id_opts *opts)
  965. {
  966. const size_t attr_sz = offsetofend(union bpf_attr, fd_by_id_token_fd);
  967. union bpf_attr attr;
  968. int fd;
  969. if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
  970. return libbpf_err(-EINVAL);
  971. memset(&attr, 0, attr_sz);
  972. attr.btf_id = id;
  973. attr.open_flags = OPTS_GET(opts, open_flags, 0);
  974. attr.fd_by_id_token_fd = OPTS_GET(opts, token_fd, 0);
  975. fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz);
  976. return libbpf_err_errno(fd);
  977. }
  978. int bpf_btf_get_fd_by_id(__u32 id)
  979. {
  980. return bpf_btf_get_fd_by_id_opts(id, NULL);
  981. }
  982. int bpf_link_get_fd_by_id_opts(__u32 id,
  983. const struct bpf_get_fd_by_id_opts *opts)
  984. {
  985. const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
  986. union bpf_attr attr;
  987. int fd;
  988. if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
  989. return libbpf_err(-EINVAL);
  990. memset(&attr, 0, attr_sz);
  991. attr.link_id = id;
  992. attr.open_flags = OPTS_GET(opts, open_flags, 0);
  993. fd = sys_bpf_fd(BPF_LINK_GET_FD_BY_ID, &attr, attr_sz);
  994. return libbpf_err_errno(fd);
  995. }
  996. int bpf_link_get_fd_by_id(__u32 id)
  997. {
  998. return bpf_link_get_fd_by_id_opts(id, NULL);
  999. }
  1000. int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
  1001. {
  1002. const size_t attr_sz = offsetofend(union bpf_attr, info);
  1003. union bpf_attr attr;
  1004. int err;
  1005. memset(&attr, 0, attr_sz);
  1006. attr.info.bpf_fd = bpf_fd;
  1007. attr.info.info_len = *info_len;
  1008. attr.info.info = ptr_to_u64(info);
  1009. err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz);
  1010. if (!err)
  1011. *info_len = attr.info.info_len;
  1012. return libbpf_err_errno(err);
  1013. }
  1014. int bpf_prog_get_info_by_fd(int prog_fd, struct bpf_prog_info *info, __u32 *info_len)
  1015. {
  1016. return bpf_obj_get_info_by_fd(prog_fd, info, info_len);
  1017. }
  1018. int bpf_map_get_info_by_fd(int map_fd, struct bpf_map_info *info, __u32 *info_len)
  1019. {
  1020. return bpf_obj_get_info_by_fd(map_fd, info, info_len);
  1021. }
  1022. int bpf_btf_get_info_by_fd(int btf_fd, struct bpf_btf_info *info, __u32 *info_len)
  1023. {
  1024. return bpf_obj_get_info_by_fd(btf_fd, info, info_len);
  1025. }
  1026. int bpf_link_get_info_by_fd(int link_fd, struct bpf_link_info *info, __u32 *info_len)
  1027. {
  1028. return bpf_obj_get_info_by_fd(link_fd, info, info_len);
  1029. }
  1030. int bpf_raw_tracepoint_open_opts(int prog_fd, struct bpf_raw_tp_opts *opts)
  1031. {
  1032. const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint);
  1033. union bpf_attr attr;
  1034. int fd;
  1035. if (!OPTS_VALID(opts, bpf_raw_tp_opts))
  1036. return libbpf_err(-EINVAL);
  1037. memset(&attr, 0, attr_sz);
  1038. attr.raw_tracepoint.prog_fd = prog_fd;
  1039. attr.raw_tracepoint.name = ptr_to_u64(OPTS_GET(opts, tp_name, NULL));
  1040. attr.raw_tracepoint.cookie = OPTS_GET(opts, cookie, 0);
  1041. fd = sys_bpf_fd(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz);
  1042. return libbpf_err_errno(fd);
  1043. }
  1044. int bpf_raw_tracepoint_open(const char *name, int prog_fd)
  1045. {
  1046. LIBBPF_OPTS(bpf_raw_tp_opts, opts, .tp_name = name);
  1047. return bpf_raw_tracepoint_open_opts(prog_fd, &opts);
  1048. }
  1049. int bpf_btf_load(const void *btf_data, size_t btf_size, struct bpf_btf_load_opts *opts)
  1050. {
  1051. const size_t attr_sz = offsetofend(union bpf_attr, btf_token_fd);
  1052. union bpf_attr attr;
  1053. char *log_buf;
  1054. size_t log_size;
  1055. __u32 log_level;
  1056. int fd;
  1057. bump_rlimit_memlock();
  1058. memset(&attr, 0, attr_sz);
  1059. if (!OPTS_VALID(opts, bpf_btf_load_opts))
  1060. return libbpf_err(-EINVAL);
  1061. log_buf = OPTS_GET(opts, log_buf, NULL);
  1062. log_size = OPTS_GET(opts, log_size, 0);
  1063. log_level = OPTS_GET(opts, log_level, 0);
  1064. if (log_size > UINT_MAX)
  1065. return libbpf_err(-EINVAL);
  1066. if (log_size && !log_buf)
  1067. return libbpf_err(-EINVAL);
  1068. attr.btf = ptr_to_u64(btf_data);
  1069. attr.btf_size = btf_size;
  1070. attr.btf_flags = OPTS_GET(opts, btf_flags, 0);
  1071. attr.btf_token_fd = OPTS_GET(opts, token_fd, 0);
  1072. /* log_level == 0 and log_buf != NULL means "try loading without
  1073. * log_buf, but retry with log_buf and log_level=1 on error", which is
  1074. * consistent across low-level and high-level BTF and program loading
  1075. * APIs within libbpf and provides a sensible behavior in practice
  1076. */
  1077. if (log_level) {
  1078. attr.btf_log_buf = ptr_to_u64(log_buf);
  1079. attr.btf_log_size = (__u32)log_size;
  1080. attr.btf_log_level = log_level;
  1081. }
  1082. fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz);
  1083. if (fd < 0 && log_buf && log_level == 0) {
  1084. attr.btf_log_buf = ptr_to_u64(log_buf);
  1085. attr.btf_log_size = (__u32)log_size;
  1086. attr.btf_log_level = 1;
  1087. fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz);
  1088. }
  1089. OPTS_SET(opts, log_true_size, attr.btf_log_true_size);
  1090. return libbpf_err_errno(fd);
  1091. }
  1092. int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
  1093. __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset,
  1094. __u64 *probe_addr)
  1095. {
  1096. const size_t attr_sz = offsetofend(union bpf_attr, task_fd_query);
  1097. union bpf_attr attr;
  1098. int err;
  1099. memset(&attr, 0, attr_sz);
  1100. attr.task_fd_query.pid = pid;
  1101. attr.task_fd_query.fd = fd;
  1102. attr.task_fd_query.flags = flags;
  1103. attr.task_fd_query.buf = ptr_to_u64(buf);
  1104. attr.task_fd_query.buf_len = *buf_len;
  1105. err = sys_bpf(BPF_TASK_FD_QUERY, &attr, attr_sz);
  1106. *buf_len = attr.task_fd_query.buf_len;
  1107. *prog_id = attr.task_fd_query.prog_id;
  1108. *fd_type = attr.task_fd_query.fd_type;
  1109. *probe_offset = attr.task_fd_query.probe_offset;
  1110. *probe_addr = attr.task_fd_query.probe_addr;
  1111. return libbpf_err_errno(err);
  1112. }
  1113. int bpf_enable_stats(enum bpf_stats_type type)
  1114. {
  1115. const size_t attr_sz = offsetofend(union bpf_attr, enable_stats);
  1116. union bpf_attr attr;
  1117. int fd;
  1118. memset(&attr, 0, attr_sz);
  1119. attr.enable_stats.type = type;
  1120. fd = sys_bpf_fd(BPF_ENABLE_STATS, &attr, attr_sz);
  1121. return libbpf_err_errno(fd);
  1122. }
  1123. int bpf_prog_bind_map(int prog_fd, int map_fd,
  1124. const struct bpf_prog_bind_opts *opts)
  1125. {
  1126. const size_t attr_sz = offsetofend(union bpf_attr, prog_bind_map);
  1127. union bpf_attr attr;
  1128. int ret;
  1129. if (!OPTS_VALID(opts, bpf_prog_bind_opts))
  1130. return libbpf_err(-EINVAL);
  1131. memset(&attr, 0, attr_sz);
  1132. attr.prog_bind_map.prog_fd = prog_fd;
  1133. attr.prog_bind_map.map_fd = map_fd;
  1134. attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0);
  1135. ret = sys_bpf(BPF_PROG_BIND_MAP, &attr, attr_sz);
  1136. return libbpf_err_errno(ret);
  1137. }
  1138. int bpf_token_create(int bpffs_fd, struct bpf_token_create_opts *opts)
  1139. {
  1140. const size_t attr_sz = offsetofend(union bpf_attr, token_create);
  1141. union bpf_attr attr;
  1142. int fd;
  1143. if (!OPTS_VALID(opts, bpf_token_create_opts))
  1144. return libbpf_err(-EINVAL);
  1145. memset(&attr, 0, attr_sz);
  1146. attr.token_create.bpffs_fd = bpffs_fd;
  1147. attr.token_create.flags = OPTS_GET(opts, flags, 0);
  1148. fd = sys_bpf_fd(BPF_TOKEN_CREATE, &attr, attr_sz);
  1149. return libbpf_err_errno(fd);
  1150. }
  1151. int bpf_prog_stream_read(int prog_fd, __u32 stream_id, void *buf, __u32 buf_len,
  1152. struct bpf_prog_stream_read_opts *opts)
  1153. {
  1154. const size_t attr_sz = offsetofend(union bpf_attr, prog_stream_read);
  1155. union bpf_attr attr;
  1156. int err;
  1157. if (!OPTS_VALID(opts, bpf_prog_stream_read_opts))
  1158. return libbpf_err(-EINVAL);
  1159. memset(&attr, 0, attr_sz);
  1160. attr.prog_stream_read.stream_buf = ptr_to_u64(buf);
  1161. attr.prog_stream_read.stream_buf_len = buf_len;
  1162. attr.prog_stream_read.stream_id = stream_id;
  1163. attr.prog_stream_read.prog_fd = prog_fd;
  1164. err = sys_bpf(BPF_PROG_STREAM_READ_BY_FD, &attr, attr_sz);
  1165. return libbpf_err_errno(err);
  1166. }
  1167. int bpf_prog_assoc_struct_ops(int prog_fd, int map_fd,
  1168. struct bpf_prog_assoc_struct_ops_opts *opts)
  1169. {
  1170. const size_t attr_sz = offsetofend(union bpf_attr, prog_assoc_struct_ops);
  1171. union bpf_attr attr;
  1172. int err;
  1173. if (!OPTS_VALID(opts, bpf_prog_assoc_struct_ops_opts))
  1174. return libbpf_err(-EINVAL);
  1175. memset(&attr, 0, attr_sz);
  1176. attr.prog_assoc_struct_ops.map_fd = map_fd;
  1177. attr.prog_assoc_struct_ops.prog_fd = prog_fd;
  1178. attr.prog_assoc_struct_ops.flags = OPTS_GET(opts, flags, 0);
  1179. err = sys_bpf(BPF_PROG_ASSOC_STRUCT_OPS, &attr, attr_sz);
  1180. return libbpf_err_errno(err);
  1181. }