skel_internal.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
  2. /* Copyright (c) 2021 Facebook */
  3. #ifndef __SKEL_INTERNAL_H
  4. #define __SKEL_INTERNAL_H
  5. #ifdef __KERNEL__
  6. #include <linux/fdtable.h>
  7. #include <linux/mm.h>
  8. #include <linux/mman.h>
  9. #include <linux/slab.h>
  10. #include <linux/bpf.h>
  11. #else
  12. #include <unistd.h>
  13. #include <sys/syscall.h>
  14. #include <sys/mman.h>
  15. #include <linux/keyctl.h>
  16. #include <stdlib.h>
  17. #include "bpf.h"
  18. #endif
  19. #ifndef SHA256_DIGEST_LENGTH
  20. #define SHA256_DIGEST_LENGTH 32
  21. #endif
  22. #ifndef __NR_bpf
  23. # if defined(__mips__) && defined(_ABIO32)
  24. # define __NR_bpf 4355
  25. # elif defined(__mips__) && defined(_ABIN32)
  26. # define __NR_bpf 6319
  27. # elif defined(__mips__) && defined(_ABI64)
  28. # define __NR_bpf 5315
  29. # endif
  30. #endif
  31. /* This file is a base header for auto-generated *.lskel.h files.
  32. * Its contents will change and may become part of auto-generation in the future.
  33. *
  34. * The layout of bpf_[map|prog]_desc and bpf_loader_ctx is feature dependent
  35. * and will change from one version of libbpf to another and features
  36. * requested during loader program generation.
  37. */
  38. struct bpf_map_desc {
  39. /* output of the loader prog */
  40. int map_fd;
  41. /* input for the loader prog */
  42. __u32 max_entries;
  43. __aligned_u64 initial_value;
  44. };
  45. struct bpf_prog_desc {
  46. int prog_fd;
  47. };
  48. enum {
  49. BPF_SKEL_KERNEL = (1ULL << 0),
  50. };
  51. struct bpf_loader_ctx {
  52. __u32 sz;
  53. __u32 flags;
  54. __u32 log_level;
  55. __u32 log_size;
  56. __u64 log_buf;
  57. };
  58. struct bpf_load_and_run_opts {
  59. struct bpf_loader_ctx *ctx;
  60. const void *data;
  61. const void *insns;
  62. __u32 data_sz;
  63. __u32 insns_sz;
  64. const char *errstr;
  65. void *signature;
  66. __u32 signature_sz;
  67. __s32 keyring_id;
  68. void *excl_prog_hash;
  69. __u32 excl_prog_hash_sz;
  70. };
  71. long kern_sys_bpf(__u32 cmd, void *attr, __u32 attr_size);
  72. static inline int skel_sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
  73. unsigned int size)
  74. {
  75. #ifdef __KERNEL__
  76. return kern_sys_bpf(cmd, attr, size);
  77. #else
  78. return syscall(__NR_bpf, cmd, attr, size);
  79. #endif
  80. }
  81. #ifdef __KERNEL__
  82. static inline int close(int fd)
  83. {
  84. return close_fd(fd);
  85. }
  86. static inline void *skel_alloc(size_t size)
  87. {
  88. struct bpf_loader_ctx *ctx = kzalloc(size, GFP_KERNEL);
  89. if (!ctx)
  90. return NULL;
  91. ctx->flags |= BPF_SKEL_KERNEL;
  92. return ctx;
  93. }
  94. static inline void skel_free(const void *p)
  95. {
  96. kfree(p);
  97. }
  98. /* skel->bss/rodata maps are populated the following way:
  99. *
  100. * For kernel use:
  101. * skel_prep_map_data() allocates kernel memory that kernel module can directly access.
  102. * Generated lskel stores the pointer in skel->rodata and in skel->maps.rodata.initial_value.
  103. * The loader program will perform probe_read_kernel() from maps.rodata.initial_value.
  104. * skel_finalize_map_data() sets skel->rodata to point to actual value in a bpf map and
  105. * does maps.rodata.initial_value = ~0ULL to signal skel_free_map_data() that kvfree
  106. * is not necessary.
  107. *
  108. * For user space:
  109. * skel_prep_map_data() mmaps anon memory into skel->rodata that can be accessed directly.
  110. * Generated lskel stores the pointer in skel->rodata and in skel->maps.rodata.initial_value.
  111. * The loader program will perform copy_from_user() from maps.rodata.initial_value.
  112. * skel_finalize_map_data() remaps bpf array map value from the kernel memory into
  113. * skel->rodata address.
  114. *
  115. * The "bpftool gen skeleton -L" command generates lskel.h that is suitable for
  116. * both kernel and user space. The generated loader program does
  117. * either bpf_probe_read_kernel() or bpf_copy_from_user() from initial_value
  118. * depending on bpf_loader_ctx->flags.
  119. */
  120. static inline void skel_free_map_data(void *p, __u64 addr, size_t sz)
  121. {
  122. if (addr != ~0ULL)
  123. kvfree(p);
  124. /* When addr == ~0ULL the 'p' points to
  125. * ((struct bpf_array *)map)->value. See skel_finalize_map_data.
  126. */
  127. }
  128. static inline void *skel_prep_map_data(const void *val, size_t mmap_sz, size_t val_sz)
  129. {
  130. void *addr;
  131. addr = kvmalloc(val_sz, GFP_KERNEL);
  132. if (!addr)
  133. return NULL;
  134. memcpy(addr, val, val_sz);
  135. return addr;
  136. }
  137. static inline void *skel_finalize_map_data(__u64 *init_val, size_t mmap_sz, int flags, int fd)
  138. {
  139. struct bpf_map *map;
  140. void *addr = NULL;
  141. kvfree((void *) (long) *init_val);
  142. *init_val = ~0ULL;
  143. /* At this point bpf_load_and_run() finished without error and
  144. * 'fd' is a valid bpf map FD. All sanity checks below should succeed.
  145. */
  146. map = bpf_map_get(fd);
  147. if (IS_ERR(map))
  148. return NULL;
  149. if (map->map_type != BPF_MAP_TYPE_ARRAY)
  150. goto out;
  151. addr = ((struct bpf_array *)map)->value;
  152. /* the addr stays valid, since FD is not closed */
  153. out:
  154. bpf_map_put(map);
  155. return addr;
  156. }
  157. #else
  158. static inline void *skel_alloc(size_t size)
  159. {
  160. return calloc(1, size);
  161. }
  162. static inline void skel_free(void *p)
  163. {
  164. free(p);
  165. }
  166. static inline void skel_free_map_data(void *p, __u64 addr, size_t sz)
  167. {
  168. munmap(p, sz);
  169. }
  170. static inline void *skel_prep_map_data(const void *val, size_t mmap_sz, size_t val_sz)
  171. {
  172. void *addr;
  173. addr = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE,
  174. MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  175. if (addr == (void *) -1)
  176. return NULL;
  177. memcpy(addr, val, val_sz);
  178. return addr;
  179. }
  180. static inline void *skel_finalize_map_data(__u64 *init_val, size_t mmap_sz, int flags, int fd)
  181. {
  182. void *addr;
  183. addr = mmap((void *) (long) *init_val, mmap_sz, flags, MAP_SHARED | MAP_FIXED, fd, 0);
  184. if (addr == (void *) -1)
  185. return NULL;
  186. return addr;
  187. }
  188. #endif
  189. static inline int skel_closenz(int fd)
  190. {
  191. if (fd > 0)
  192. return close(fd);
  193. return -EINVAL;
  194. }
  195. #ifndef offsetofend
  196. #define offsetofend(TYPE, MEMBER) \
  197. (offsetof(TYPE, MEMBER) + sizeof((((TYPE *)0)->MEMBER)))
  198. #endif
  199. static inline int skel_map_create(enum bpf_map_type map_type,
  200. const char *map_name,
  201. __u32 key_size,
  202. __u32 value_size,
  203. __u32 max_entries,
  204. const void *excl_prog_hash,
  205. __u32 excl_prog_hash_sz)
  206. {
  207. const size_t attr_sz = offsetofend(union bpf_attr, excl_prog_hash_size);
  208. union bpf_attr attr;
  209. memset(&attr, 0, attr_sz);
  210. attr.map_type = map_type;
  211. attr.excl_prog_hash = (unsigned long) excl_prog_hash;
  212. attr.excl_prog_hash_size = excl_prog_hash_sz;
  213. strncpy(attr.map_name, map_name, sizeof(attr.map_name));
  214. attr.key_size = key_size;
  215. attr.value_size = value_size;
  216. attr.max_entries = max_entries;
  217. return skel_sys_bpf(BPF_MAP_CREATE, &attr, attr_sz);
  218. }
  219. static inline int skel_map_update_elem(int fd, const void *key,
  220. const void *value, __u64 flags)
  221. {
  222. const size_t attr_sz = offsetofend(union bpf_attr, flags);
  223. union bpf_attr attr;
  224. memset(&attr, 0, attr_sz);
  225. attr.map_fd = fd;
  226. attr.key = (long) key;
  227. attr.value = (long) value;
  228. attr.flags = flags;
  229. return skel_sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, attr_sz);
  230. }
  231. static inline int skel_map_delete_elem(int fd, const void *key)
  232. {
  233. const size_t attr_sz = offsetofend(union bpf_attr, flags);
  234. union bpf_attr attr;
  235. memset(&attr, 0, attr_sz);
  236. attr.map_fd = fd;
  237. attr.key = (long)key;
  238. return skel_sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz);
  239. }
  240. static inline int skel_map_get_fd_by_id(__u32 id)
  241. {
  242. const size_t attr_sz = offsetofend(union bpf_attr, flags);
  243. union bpf_attr attr;
  244. memset(&attr, 0, attr_sz);
  245. attr.map_id = id;
  246. return skel_sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, attr_sz);
  247. }
  248. static inline int skel_raw_tracepoint_open(const char *name, int prog_fd)
  249. {
  250. const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint.prog_fd);
  251. union bpf_attr attr;
  252. memset(&attr, 0, attr_sz);
  253. attr.raw_tracepoint.name = (long) name;
  254. attr.raw_tracepoint.prog_fd = prog_fd;
  255. return skel_sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz);
  256. }
  257. static inline int skel_link_create(int prog_fd, int target_fd,
  258. enum bpf_attach_type attach_type)
  259. {
  260. const size_t attr_sz = offsetofend(union bpf_attr, link_create.iter_info_len);
  261. union bpf_attr attr;
  262. memset(&attr, 0, attr_sz);
  263. attr.link_create.prog_fd = prog_fd;
  264. attr.link_create.target_fd = target_fd;
  265. attr.link_create.attach_type = attach_type;
  266. return skel_sys_bpf(BPF_LINK_CREATE, &attr, attr_sz);
  267. }
  268. static inline int skel_obj_get_info_by_fd(int fd)
  269. {
  270. const size_t attr_sz = offsetofend(union bpf_attr, info);
  271. __u8 sha[SHA256_DIGEST_LENGTH];
  272. struct bpf_map_info info;
  273. __u32 info_len = sizeof(info);
  274. union bpf_attr attr;
  275. memset(&info, 0, sizeof(info));
  276. info.hash = (long) &sha;
  277. info.hash_size = SHA256_DIGEST_LENGTH;
  278. memset(&attr, 0, attr_sz);
  279. attr.info.bpf_fd = fd;
  280. attr.info.info = (long) &info;
  281. attr.info.info_len = info_len;
  282. return skel_sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz);
  283. }
  284. static inline int skel_map_freeze(int fd)
  285. {
  286. const size_t attr_sz = offsetofend(union bpf_attr, map_fd);
  287. union bpf_attr attr;
  288. memset(&attr, 0, attr_sz);
  289. attr.map_fd = fd;
  290. return skel_sys_bpf(BPF_MAP_FREEZE, &attr, attr_sz);
  291. }
  292. #ifdef __KERNEL__
  293. #define set_err
  294. #else
  295. #define set_err err = -errno
  296. #endif
  297. static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
  298. {
  299. const size_t prog_load_attr_sz = offsetofend(union bpf_attr, keyring_id);
  300. const size_t test_run_attr_sz = offsetofend(union bpf_attr, test);
  301. int map_fd = -1, prog_fd = -1, key = 0, err;
  302. union bpf_attr attr;
  303. err = map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1,
  304. opts->excl_prog_hash, opts->excl_prog_hash_sz);
  305. if (map_fd < 0) {
  306. opts->errstr = "failed to create loader map";
  307. set_err;
  308. goto out;
  309. }
  310. err = skel_map_update_elem(map_fd, &key, opts->data, 0);
  311. if (err < 0) {
  312. opts->errstr = "failed to update loader map";
  313. set_err;
  314. goto out;
  315. }
  316. #ifndef __KERNEL__
  317. err = skel_map_freeze(map_fd);
  318. if (err < 0) {
  319. opts->errstr = "failed to freeze map";
  320. set_err;
  321. goto out;
  322. }
  323. err = skel_obj_get_info_by_fd(map_fd);
  324. if (err < 0) {
  325. opts->errstr = "failed to fetch obj info";
  326. set_err;
  327. goto out;
  328. }
  329. #endif
  330. memset(&attr, 0, prog_load_attr_sz);
  331. attr.prog_type = BPF_PROG_TYPE_SYSCALL;
  332. attr.insns = (long) opts->insns;
  333. attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn);
  334. attr.license = (long) "Dual BSD/GPL";
  335. #ifndef __KERNEL__
  336. attr.signature = (long) opts->signature;
  337. attr.signature_size = opts->signature_sz;
  338. #else
  339. if (opts->signature || opts->signature_sz)
  340. pr_warn("signatures are not supported from bpf_preload\n");
  341. #endif
  342. attr.keyring_id = opts->keyring_id;
  343. memcpy(attr.prog_name, "__loader.prog", sizeof("__loader.prog"));
  344. attr.fd_array = (long) &map_fd;
  345. attr.log_level = opts->ctx->log_level;
  346. attr.log_size = opts->ctx->log_size;
  347. attr.log_buf = opts->ctx->log_buf;
  348. attr.prog_flags = BPF_F_SLEEPABLE;
  349. err = prog_fd = skel_sys_bpf(BPF_PROG_LOAD, &attr, prog_load_attr_sz);
  350. if (prog_fd < 0) {
  351. opts->errstr = "failed to load loader prog";
  352. set_err;
  353. goto out;
  354. }
  355. memset(&attr, 0, test_run_attr_sz);
  356. attr.test.prog_fd = prog_fd;
  357. attr.test.ctx_in = (long) opts->ctx;
  358. attr.test.ctx_size_in = opts->ctx->sz;
  359. err = skel_sys_bpf(BPF_PROG_RUN, &attr, test_run_attr_sz);
  360. if (err < 0 || (int)attr.test.retval < 0) {
  361. if (err < 0) {
  362. opts->errstr = "failed to execute loader prog";
  363. set_err;
  364. } else {
  365. opts->errstr = "error returned by loader prog";
  366. err = (int)attr.test.retval;
  367. #ifndef __KERNEL__
  368. errno = -err;
  369. #endif
  370. }
  371. goto out;
  372. }
  373. err = 0;
  374. out:
  375. if (map_fd >= 0)
  376. close(map_fd);
  377. if (prog_fd >= 0)
  378. close(prog_fd);
  379. return err;
  380. }
  381. #endif